当前位置: 首页>后端>正文

前端如何解决跨域问题,跨域请求如何携带cookie

一.什么是跨域

1.简介

跨域分为开发跨域(开发环境跨域)和线上跨域(生产环境跨域):
开发环境跨域:开发阶段前后端工作站不同,所以ip地址不同,请求数据必然出现跨域问题;
生产环境跨域:一个网站关联多台服务器,构成一个完整的生产服务器集群。不同的服务器之间通过地址进行通信,就算在局域网中,端口地址也是不一样的,就会产生跨域问题。

2.同源策略

跨域问题其实就是浏览器的同源策略所导致的。同源策略是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到攻击。所谓同源是指"协议+域名+端口"三者相同(注:即便两个不同的域名指向同一个ip地址,也非同源)不同源之间相互请求资源,就算作“跨域”。
注:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。


前端如何解决跨域问题,跨域请求如何携带cookie,第1张

但是有一些标签是允许跨域加载资源:

<img src="xxx">
<link href="xxx">
<script src="xxx">

一.解决跨域

1.JSONP (线上跨域解决方案)

前端+后端共同解决)


前端如何解决跨域问题,跨域请求如何携带cookie,第2张

JSONP 跨域主要就是利用了 script 标签没有跨域限制的这个特性。
通过script标签src属性,发送带有callback参数的get请求,服务端将返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,拿到callback函数返回的数据:

<script type="text /javascript"> 
    window.jsonpCallback = function (res) { console.log(res); }
</script>
<script src="http://xx/api/jsonp?msg=abc&callback=jsonpCallback"  type="text/javascript"></script>
// 相应后端实现
app.use(async (ctx, next) => {  
  if (ctx.path === "/api/jsonp") {    
    const { callback, msg } = ctx.query;    
    ctx.body = `${callback.stringify({ msg })})`;
    return;  
    }
});

jsonp的缺点:只能发送get一种请求。

2 跨域资源共享(CORS)(线上跨域解决方案)

(服务端解决的方式)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器发出请求,从而解决了Ajax只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所==有浏览器都支持该功能,IE浏览器不能低于IE10。

我们只需要在后端代码上增加一个跨域请求响应头:Access-Control-Allow-Origin
例如php中的 header(Access-Control-Allow-Origin:*) *表示所有请求地址都允许跨域响应。

3.代理服务器

vue项目开发环境跨域问题
1.在vue.config.js里配置

// 跨域的代理中转服务器服务
proxy: {
    "/api":{   // /vue代理target
        target: 'http://10.1.XXX.XXX:8088',      // 后端接口的根目录
        // secure: true,           // 如果是 https ,需要开启这个选项,http为false
        changeOrigin: true,        // 是否跨域
        pathRewrite: {            // 是否重写路径,看代理前端路径是否与后端路径一致
          '^/api':'', //将所有含/api路径的,去掉/api转发给服务器                 
        }
    }
},

2.react项目开发环境跨域问题

npm i http-proxy-middleware -S

项目src中新建文件setupProxy.js,名字不能更改,必须是这个

//setupProxy.js内容
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
  app.use(
    proxy.createProxyMiddleware('/api', {
      target: process.env.REACT_APP_BASE_URL, //你需要访问的地址
      changeOrigin: true,
      // secure: false,
      pathRewrite: {'^/api': ''}
    })
  )
}

3.nginx代理

server {
  listen 8888;
  server_name localhost;
  location /api/ {
      proxy_pass http://targetserver.com/api/;
      add_header Access-Control-Allow-Origin *;
      # 其他配置
  }
}

在上面的配置中,/api/ 是要跨域访问的接口路径,http://targetserver.com/api/ 是目标服务器的接口地址。当请求到达 Nginx 后,Nginx 会将请求代理到目标服务器,同时在响应头中添加 Access-Control-Allow-Origin 信息,允许所有源跨域访问。

4.Websocket方式解决跨域

使用Websocket也可以解决跨域问题,因为WebSocket本身不存在跨域问题,所以我们可以利用webSocket来进行非同源之间的通信,

二.跨域请求携带cookie

默认情况下是跨域是不会携带cookie的,例如:a.com 网站请求 b.com 的接口,这个时候不会把a.com这个域名下的 cookie 携带上。如果需要携带,则需要做一下配置

1.前端配置

XMLHttpRequest发请求需要设置

withCredentials=true

fetch 发请求需要设置

credentials = include

axios发请求配置:

axios.defaults.withCredentials = true

2.服务端配置

Access-Control-Allow-Credentials: true

Access-Control-Allow-Origin: [特定域名] // 不能设置为 “” 或 *,而要设置为客户端发送请求时的IP地址

因为最新版本谷歌浏览器 samesite 属性默认是 lax,lax 模式在很多情况都是不允许跨域携带cookie,所以必须要把 samesite设置为 none, 但是设置为 none 有一个要求,就是必须 secure 属性为 true,也就是必须使用 https 。

设置 cookie 增加配置

sameSite: 'none'
secure: true

https://www.xamrdz.com/backend/3qr1920666.html

相关文章: