跨域請求中常見的幾個問題

一. Header相關的幾個概念

CORS: 跨域資源共享(CORS) 是一種機制,它使用額外的?HTTP頭來告訴瀏覽器? 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。

出于安全原因,瀏覽器限制從腳本內發起的跨源HTTP請求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非響應報文包含了正確CORS響應頭。

origin: web的origin 被定義為由協議,域和端口組成的 URL訪問。僅當協議,域和端口全部匹配,兩對象才具有相同的origin。

Access-Control-Allow-Origin: 該響應是否可以與來自給定的請求代碼共享origin。??

Access-Control-Allow-Origin:*? #允許任何源的代碼訪問資源
Access-Control-Allow-Origin:?https://developer.mozilla.org? #允許請求來自https://developer.mozilla.org 的代碼訪問資源。

Access-Control-Allow-Methods: 在對preflight request(預檢請求)的應答中明確了客戶端所要訪問的資源允許使用的方法或方法列表

Access-Control-Allow-Methods POST,GET,OPTIONS,PUT

Access-Control-Allow-Headers: ?用于preflight request(預檢請求)種,列出了將會在正式請求的Access-Control-Expose-Headers 字段中出現的首部信息,用于響應包含在Access-Control-Request-Headers 首部的預檢請求。

Access-Control-Allow-Headers Content-Type,access-control-allow-credentials,access-control-allow-origin

Access-Control-Max-Age: 這個響應首部表示preflight request(預檢請求)的返回結果(即?Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息)?可以被緩存多久。

Access-Control-Max-Age: 600 #

CORS中的預檢請求(option): 在 CORS 中,可以使用 OPTIONS 方法發起一個預檢請求(一般都是瀏覽檢測到請求跨域時,會自動發起),以檢測實際請求是否可以被服務器所接受。預檢請求報文中的 Access-Control-Request-Method首部字段告知服務器實際請求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服務器實際請求所攜帶的自定義首部字段。服務器基于從預檢請求獲得的信息來判斷,是否接受接下來的實際請求。

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: //foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

服務器所返回的 Access-Control-Allow-Methods 首部字段將所有允許的請求方法告知客戶端。該首部字段與 Allow 類似,但只能用于涉及到 CORS 的場景中。

想要了解更多的http header信息 請訪問 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

二. 跨域常見問題排查(CORS場景)

2.1. 未配置?Access-Control-Allow-Origin。

Access to XMLHttpRequest at '//foo1.example.com/' from origin '//foo2.example.com/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

解決方法: 在域為foo1.example.com?的虛擬主機添加 Access-Control-Allow-Origin 值為//foo2.example.com。

server {
? ? ...
? ? server_name foo1.example.com;
? ? ...
? ? add_header 'Access-Control-Allow-Origin' '//foo2.example.com';
? ??add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';

????if ($request_method = "OPTIONS")??{
????????return 204;
????}
? ? ...
}

2.2. 跨域訪問

Access to XMLHttpRequest at '//foo1.example.com/' from origin '//foo3.example.com/' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value '//foo2.example.com/' that is not equal to the supplied origin.

?解決方法:請注意觀察上述報錯, Access-Control-Allow-Origin 已經至少有一個值為//foo2.example.com?的設定。所以現在配置一個允許多源訪問的配置。

server {
????...
????server_name foo1.example.com;
????...
? ? if ( $http_origin ~ .*.(example|aldwx).(net|com)) {
? ? ? ? set $other_domain $http_origin;
? ? }

? ? add_header Access-Control-Allow-Origin $other_domain;
? ??add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';

? ? if ($request_method = "OPTIONS")??{
? ? ? ? return 204;
? ? }
? ? ...
}

2.3.? Access-Control-Allow-Headers 中首部缺失

Access to XMLHttpRequest at '//foo1.example.com/' from origin '//foo2.example.com/' has been blocked by CORS policy: Request header field <u>cookies</u> is not allowed by Access-Control-Allow-Headers in preflight response.

解決方法: 遇到這一類的問題時,需要仔細閱讀報錯,在報錯里面基本已經寫明了答案。例如上面的這個報錯信息。域foo2.example.com 請求域foo1.example.com 時,因首部cookies 未包含在?Access-Control-Allow-Headers 中,所以foo1無法響應客戶端請求。并且這一類問題可能同時會出現幾個首部缺失的請求,但是報錯是單個出現,所以呢,要仔細閱讀錯誤。下面也是其中一個報錯

Access to XMLHttpRequest at '//foo1.example.com/' from origin '//foo2.example.com/' has been blocked by CORS policy: Request header field <u>access-control-allow-credentials</u>?is not allowed by Access-Control-Allow-Headers in preflight response.
server {
????...
????server_name foo1.example.com;
????...
?????
????if ( $http_origin ~ .*.(example|aldwx).(net|com)) {
????????set $other_domain $http_origin;
????}

????add_header Access-Control-Allow-Origin $other_domain;
? ??add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
? ? add_header Access-Control-Allow-Headers 'access-control-allow-credentials,cookies,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

????if ($request_method = "OPTIONS")??{
????????return 204;
????}
????...
}

參考文章:
Nginx配置跨域請求 Access-Control-Allow-Origin *

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

posted @ 2019-06-06 18:43 guoew 閱讀(...) 評論(...) 編輯 收藏