跨域告警未开放 Access-Control-Allow-Origin
解决方案:在对应网页 location 添加以下跨域配置:
Access-Control-Allow-Origin: *
或 Access-Control-Allow-Origin: 'http://doman:port'
1. 简单请求
在 CORS 出现前,发送 HTTP 请求时在头信息中不能包含任何自定义字段,且 HTTP 头信息不超过以下几个字段:
主动设置的头信息不能超过以下字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain)
请求方法只能是:HEAD,GET,POST
浏览器会在 请求头信息 里增加一个 Origin 字段,表明本次请求的来源,若服务器返回的头部信息里需包含 Access-Control-Allow-Origin,并包含 Origin 则浏览器正常返回数据,否则出现跨域错误。
如果需要携带 cookie,请求时需设置 (比如 XMLHttpRequest.withCredentials = true)。若返回头部信息有 Access-Control-Allow-Credentials:true
,则浏览器会正常返回数据,否则浏览器会拦截结果报 跨域错误。
注意:服务器会正常返回数据,只是浏览器拦截了结果。
服务器在返回头信息里设置(必须):
Access-Control-Allow-Origin: Origin
Eg:Access-Control-Allow-Origin:127.0.0.1:80
如果想设置匹配所有的 Origin 且不带 cookie 的,可以设置:
Access-Control-Allow-Origin: *
如果需要带 Cookie(用户是否可以发送、处理 cookie),需设置:
Access-Control-Allow-Credentials:true
如果想匹配所有的 Origin 且带 cookie:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: 请求的 Origin(从 request 获取后填入)千万不能同时设置 Credentials=true 且 Origin=*,浏览器会报错。Access-Control-Expose-Headers:可选,可以让用户拿到的字段。
有几个字段无论设置与否都可以拿到的,包括:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
2. 非简单请求
不能同时满足简单请求的 2 个条件。
常见的情况是请求方法是 PUT 或者 Content-Type 字段类型是 application/json 或者 头信息里自定义了属性
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers Accept,Origin,X-Requested-With,Content-Type,Last-Modified,JSESSIONID,token;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
if ($request_method = 'OPTIONS'){return 204;}
或者
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
解释:
1、Access-Control-Allow-Origin,这里使用变量 $http_origin 取得当前来源域,也可以用“*”代表允许所有;
2、Access-Control-Allow-Credentials,为 true 的时候指请求时可带上 Cookie,自己按情况配置吧;
3、Access-Control-Allow-Methods,OPTIONS 一定要有的,另外一般也就 GET 和 POST,如果你有其它的也可加进去;
4、Access-Control-Allow-Headers,这个要注意,里面一定要包含自定义的 http 头字段(就是说前端请求接口时,如果在 http 头里加了自定义的字段,这里配置一定要写上相应的字段),从上面可看到我写的比较长,我在网上搜索一些常用的写进去了,里面有“web-token”和“app-token”,这个是我项目里前端请求时设置的,所以我在这里要写上;
5、Access-Control-Expose-Headers,可不设置,看网上大致意思是默认只能获返回头的 6 个基本字段,要获取其它额外的,先在这设置才能获取它;
6、语句“if ($request_method =‘OPTIONS’) {”,因为浏览器判断是否允许跨域时会先往后端发一个 options 请求,然后根据返回的结果判断是否允许跨域请求,所以这里单独判断这个请求,然后直接返回;
完整跨域配置参考:
nginx:
server {
listen 80 default_server;
server_name _;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;
location /file {if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods $http_access_control_request_method;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
add_header Access-Control-Max-Age 1728000;
return 204;
}
}
}
java:
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 支持 cookie 跨域
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setMaxAge(300L);// 设置时间有效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
微信扫描下方的二维码阅读本文