HTML5 的到來促進了前後端分離開發的發展,所謂分離即分離接口和頁面。 部署的時候一般都把接口部署在單獨的域名下面,帶上 api 字首,頁面則用主域名。 例如:
頁面域名:www.example.com
接口域名則為:api.example.com
同源政策
同源政策 限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行互動。這是一個用于隔離潛在惡意檔案的重要安全機制。
上面的兩個域名不相同,是以會被浏覽器所限制,頁面中 ajax 調用 api.example.com 接口 将不會成功。一般錯誤如下:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin XXX is therefore not allowed access. The response had HTTP status 4XX.
使用 nginx 解決跨域
一開始網上找了很多教程,都說的不清楚,寫的也不完整,索性研究了一下文檔,幫大家趟個坑。
if ($request_method = 'OPTIONS') {
return 204;
}
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
add_header Access-Control-Max-Age 86400 always;複制代碼
解析:
這裡判斷請求方法是否為 OPTIONS,OPTIONS 請求方法為預檢請求,當浏覽器發現需要跨域請求 的時候會先使用該方法請求伺服器,伺服器需要傳回正确的資訊後浏覽器才會接着發送正式請求(一般除了 GET 方法外的跨域請求都會先發送預檢請求),預檢請求的傳回狀态碼為 204 代表成功,其它均為失敗。 預檢請求沒有傳回的 Body。
if ($request_method = 'OPTIONS') {
return 204;
}複制代碼
這裡在傳回頭中添加 Access-Control-Allow-Origin 為 *,代表允許所有域名下的頁面來請求這個 位址(不推薦這樣做,一般直接指定為域名,比如 www.example.com)。
add_header Access-Control-Allow-Origin * always;複制代碼
這裡在傳回頭中添加 Access-Control-Allow-Headers,代表允許在請求該位址的時候帶上指定的 請求頭,例如:Content-Type,Authorization,使用逗号(,)拼接起來放在雙引号(")中。 需要在請求頭中帶上其他自定義頭的自行添加。
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;複制代碼
這裡在傳回頭中添加 Access-Control-Allow-Methods,代表允許使用指定的方法請求該位址。
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;複制代碼
這裡添加了 Access-Control-Max-Age,它代表着在 86400 秒之内不用請求該位址的時候 不需要再進行預檢請求,也就是跨域緩存。根據需要設定時長就行。
add_header Access-Control-Max-Age 86400 always;複制代碼
注意:上面的 add_header 最後都加上了 always,它表示不管傳回狀态碼是多少都 會使 add_header 生效,有些時候服務端可能會傳回 4XX 的狀态碼,這時候如果少了 always 會導緻 add_header 失效,進而導緻浏覽器報跨域錯誤。 參考nginx文檔