使用场景
后端服务和前端服务不在同一台主机,且前后端通过接口形式传送数据。
eg:前端资源存在CDN上(awp项目),这样前后端无法公用一台服务主机,需要借助 CORS来解决跨域问题。
配置项
前端
和普通的ajax请求,没有太多区别。如果需要携带cookie,angularjs的可以这样配置,其他配置方式自行google
.config([
'$httpProvider'
, function ($httpProvider) {
$httpProvider.defaults.withCredentials =
true
;
}])
|
后端
CORS 更多的是需要后端支持,后端再返回数据时,需要设置 header。
public
void
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws
IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String origin = request.getHeader(
"Origin"
);
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader(
"Access-Control-Allow-Origin"
, origin);
response.setHeader(
"Access-Control-Allow-Credentials"
,
"true"
);
response.setHeader(
"Access-Control-Allow-Methods"
,
"POST, GET, PUT, PATCH, DELETE, OPTIONS"
);
response.setHeader(
"Access-Control-Allow-Headers"
,
"Origin, Content-Type, Accept, __skcy, x-requested-with"
);
response.setHeader(
"Access-Control-Max-Age"
,
"1728000"
);
if
(!request.getMethod().equalsIgnoreCase(
"options"
)) {
filterChain.doFilter(servletRequest, servletResponse);
}
}
|
Preflighted Requests
Preflighted Requests是CORS中一种透明服务器验证机制。预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTIONS 请求头,其目的就是为了判断实际发送的请求是否是安全的(GET 请求不会发送), 触发预检请求之后,这时候当后端配置的 Access-Control-Allow-Methods 属性中没有包含OPTIONS类型的请求,浏览器发送的OPTIONS试探请求没有被接受,请求就终止了。
OPTIONS 请求不会携带 cookie,如果需要根据cokie进行认证判断,需要对 OPTIONS 进行过滤。
if
(!request.getMethod().equalsIgnoreCase(
"options"
)) {
filterChain.doFilter(servletRequest, servletResponse);
}
|
缓存 OPTIONS
cors post 请求,一般会发两个请求,第一个请求是 OPTIONS,就是上面提到的预检请求,预检请求通过才会真正的发送POST请求
为了减少预检请求的次数,需要设置OPTIONS缓存时间,在规定的时间,不用再次发送 OPTIONS 请求。
response.setHeader(
"Access-Control-Max-Age"
,
"1728000"
);
|
随后的 POST 请求,在设置的缓存时间内,不会重复发 OPTIONS,检索HTTP请求数据。
CORS 请求成功
document.domain
前后端资源所在的服务器的根域名一样,可以通过设置document.domain来实现跨越请求。
document.domain = 'meituan.com'
其他方案
- jsonp
- nginx、node 转发