瀏覽器同源策略
同源策略是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屬性。
參考資料
轉自 https://www.jianshu.com/p/4da65de0c02b
