浏览器同源策略
同源策略是Web应用程序安全模型中的一个重要概念。根据该策略,Web浏览器允许第一个Web页面中包含的脚本访问第二个Web页面中的数据,但前提是两个Web页面具有相同的源。同源定义为协议,主机名和端口号相同的组合。此策略可防止一个页面上的恶意脚本通过该页面的文档对象模型访问另一个网页上的敏感数据
AJAX规避同源策略三种方式
JSONP:介绍可见参考资料;
WebCocket:使用ws://
(非加密)和wss://
(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
CORS(本文重点):跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET
请求,CORS允许任何类型的请求。
Nginx通过CORS,实现跨域
Nginx标准配置
server {
... ...
# #设置跨域配置 Start
set $cors_origin "";
if ($http_origin ~* "^http://api.xx.com$"){
set $cors_origin $http_origin;
}
add_header Access-Control-Allow-Origin $cors_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 DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,x-auth-token always;
add_header Access-Control-Max-Age 1728000 always;
# 预检请求处理
if ($request_method = OPTIONS) {
return 204;
}
# #设置跨域配置 End
... ...
}
1.设置Origin:表示服务器可以接受的请求
add_header Access-Control-Allow-Origin http://api.baidu.com
表示 http://api.baidu.com
可以请求数据。这个可以设置为*星号
代表任意跨源请求都支持,但不建议这样设置;因为设置为*星号
将不在支持发送Cookie。
2.设置多域名配置
set $cors_origin "";
if ($http_origin ~* "^http://api.xx.com$"){
set $cors_origin $http_origin;
}
if ($http_origin ~* "^http://api2.xx.com$"){
set $cors_origin $http_origin;
}
这个写法主要是为了支持多域名设置,通过对请求origin的判断是否与指定跨域源一致,然后在进行header的设置;
3.设置跨域支持的请求类型
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS always;
4.设置跨域请求是否允许发送Cookie,true:支持,false:不支持
add_header Access-Control-Allow-Credentials true always;
5.设置跨域请求允许的Header头信息字段,以逗号分隔的字符串
add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,x-auth-token always;
注:需要特别注意,凡是API中约定了自定义Header,都需要在这里增加,否则不可以跨域请求。
6.本次预检请求的有效期,单位为秒,在允许缓存该条请求回应1728000秒内,无需在发出一条预检请求。
add_header Access-Control-Max-Age 1728000 always;
7.always 参数的定义
... ... always
Nginx 规则 add_header默认只会加入到指定response code
的请求中;
见官网介绍:
Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location
Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0). The value can contain variables.
指定了 always
则无论什么请求都添加header
:
If the always parameter is specified (1.7.5), the header field will be added regardless of the response code.
8.预检请求处理
if ($request_method = OPTIONS) {
return 204;
}
CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight);浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
"预检"请求用的请求方法是OPTIONS
,表示这个请求是用来询问的,因此我们需要在Nginx配置中,针对预检请求进行处理,直接返回204 & Response Header,表示服务器支持允许跨源的访问。
AJAX配置
xhr.withCredentials = false;
CORS请求默认不发送Cookie和HTTP认证信息,如果需要支持除了服务端增加设置,AJAX请求中打开withCredentials
属性。