1. 程式人生 > 實用技巧 >Nginx 跨域設定(CORS)

Nginx 跨域設定(CORS)

瀏覽器同源策略

同源策略是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