跨域支持

37 阅读3分钟

一、nginx允许跨域

        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS always;
        add_header Access-Control-Allow-Credentials true always;
        add_header Access-Control-Allow-Headers * always;
#处理预检请求
        add_header Access-Control-Max-Age 6000 always;
        if ($request_method = 'OPTIONS') {
                return 204;
        }

注意点

1、请求携带cookies

1、同域名下发送ajax请求,请求中默认会携带cookie

2、ajax在发送跨域请求时,默认情况下是不会携带cookie的

3、ajax在发送跨域请求时如果想携带cookie,必须将请求对象的withcredentials属性设置为true。

4、此时服务端的响应头Access-Control-Allow-Origin不能为*(星号)了,必须是白名单样式,也就是必须设置允许哪些url才能访问,如:

Access-Control-Allow-Origin: api.bob.com

5、除了对响应头Access-Control-Allow-Origin的设置,还必须设置另外一个响应头:Access-Control-Allow-Credentials:true。

2、withcredentials属性设置为true无效

在chrome 80版本之后,谷歌把cookie的SameSite属性,从None改成了Lax。这时候,会导致cookie因为跨站而导致不会自动带上!

所以需要后台在请求返回的时候 添加设置SiteSame 属性为 None 。

response.setHeader("Set-Cookie", "SameSite=None;Secure;JSESSIONID=xxx");

二、前端处理预检请求

后的未对OPTIONS预检/请求添加判断处理时,需要前端控制不发送预检请求处理如下:

//使用FormData参数格式 + axios的data字段
//使用formData发送请求时,axios不会预先发送option请求,直接只有一个post请求

let formData = new FormData();
formData.append('token', myToken);
axios({
    method: 'post',
    url: myUrl,
    data: formData,
})

预检请求概念

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)

"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错

除了Origin字段,"预检"请求的头信息包括两个特殊字段:

Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法

Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

简单请求

请求方法是以下三种方法之一:

HEAD
GET
POST

Content-Type: (仅当POST方法的Content-Type值等于下列之一才算做简单需求)

text/plain
multipart/form-data
application/x-www-form-urlencoded

非简单请求

请求方法不是GET/HEAD/POST
POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
请求设置了自定义的header字段

三、无nginx时java处理

四、axios跨域请求

axios
        .request({
          url: '/api/common/operator/getInfo',
          method: 'post', // 默认值
          baseURL: 'https://192.168.6.120/',
          timeout: 10000,
          withcredentials: true,
          data: {
            test: 'test'
          }
        })
        .then((response) => {
          // 处理成功情况
          console.log(response)
        })
        .catch((error) => {
          // 处理错误情况
          console.log(error)
        })