SpringCloud 跨域访问问题

简介

场景

vue 前端访问资源时,出现 CORS 跨域访问问题。

原因

跨域访问可能导致:恶意网站的 js 等脚本利用本地 cookie 免登陆访问金融、社交等关键网站。故此浏览器禁止跨域访问 response 中没用显式标名允许外链访问的网站。

具体可以参考这篇标题党的文章(内容还不错):不要再问我跨域的问题了

解决

浏览器方式

2020.05.14 最新的谷歌浏览器允许访问跨域资源方式:

--disable-web-security --user-data-dir=G:\ChromeCache

其中 user-data-dir 标签后面对应指定的浏览器缓存文件夹路径。新建谷歌浏览器快捷方式,右键属性,在“目标”的路径后面加上这些参数即可。

后端允许跨域访问

参考:注解@CrossOrigin解决跨域问题

以 SpringCloud 为例,在 controller 的资源加注解:@CrossOrigin 即可。

中间件解决方式

参考:Nginx配置跨域请求 Access-Control-Allow-Origin *

注:将所有接口暴露时一定要注意网络安全!

在 nginx 配置中添加:

1
2
3
4
5
6
7
8
# 允许跨域访问
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, DELETE' always;
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;

if ($request_method = 'OPTIONS') {
return 204;
}

跨域访问报错分析

报错’Access-Control-Allow-Origin’

The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. Origin ‘http://pre.promotion.jmxy.moc...' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

查看 response ,Access-Control-Allow-Credentials设置为true的情况下
Access-Control-Allow-Origin不能设置为 *。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
set $origin '*';
if ($http_origin) {
set $origin "$http_origin";
}

add_header Access-Control-Allow-Origin "$origin";
add_header Access-Control-Allow-Credentials "true";
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, DELETE';
add_header Access-Control-Allow-Headers 'Origin,Access-Control-Request-Headers,Access-Control-Allow-Headers,DNT,X-Requested-With,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-M
odified-Since,Cache-Control,Content-Type,Accept,Connection,Cookie,X-XSRF-TOKEN,X-CSRF-TOKEN,Authorization';

if ($request_method = 'OPTIONS') {
return 204;
}
  1. Access-Control-Allow-Origin
    服务器默认是不被允许跨域的。给Nginx服务器配置Access-Control-Allow-Origin *后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
  2. Access-Control-Allow-Headers 是为了防止出现以下错误:Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. 这个错误表示当前请求Content-Type的值不被支持。其实是我们发起了”application/json”的类型请求导致的。这里涉及到一个概念:预检请求(preflight request),请看下面”预检请求”的介绍。
  3. Access-Control-Allow-Methods 是为了防止出现以下错误:
    Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
  4. 给OPTIONS 添加 204的返回,是为了处理在发送POST请求时Nginx依然拒绝访问的错误
    发送”预检请求”时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。
Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

检查是否缺少对 option 的判断

1
2
3
if ($request_method = 'OPTIONS') {
return 204;
}