強制HTTPS (HSTS) 導(dǎo)致 CORS preflight 請求失敗的問題
最近遇到個問題前翎,跨域 PUT 請求的時候稚配,后端已經(jīng)設(shè)置好 Access-Control-Allow-Origin
頭信息了,然而瀏覽器還是報:
Access to XMLHttpRequest at 'http://abc.example.com/api/v3/xxx/1' from origin 'http://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
根據(jù)MDN的說法港华,當(dāng)進行一個簡單請求(Simple Requests)的時候道川,瀏覽器是不需要發(fā)出預(yù)檢請求(Preflight Request)的。但是如果不是簡單請求,則瀏覽器會先通過 OPTIONS
方法發(fā)出一個預(yù)檢請求冒萄,以判斷該地址是否支持CORS.
關(guān)于什么是簡單請求可以參考 HTTP訪問控制(CORS) - HTTP | MDN 中的定義臊岸,我們上面使用的PUT請求方法便不是簡單請求,那么瀏覽器就要先發(fā)出一個 OPTIONS
請求到服務(wù)器尊流。然而帅戒,我的服務(wù)器已經(jīng)設(shè)置好了應(yīng)對預(yù)檢請求的響應(yīng)力试,怎么還是不行呢每强?
仔細(xì)一看,關(guān)鍵還在于最后一句:Redirect is not allowed for a preflight request.
(預(yù)檢請求不允許重定向重定向)慨飘。這時我更加納悶响疚,我這個地址并沒有重定向呀鄙信?于是我打開開發(fā)者工具,在Network頁中看到忿晕,服務(wù)器返回的Status Code 是 307 Internal Redirect
装诡,返回的header是:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://example.com
Location: https://abc.example.com/api/v3/xxx/1
Non-Authoritative-Reason: HSTS
原來,服務(wù)器端的Nginx開啟了HSTS (HTTP Strict Transport Security) HTTP嚴(yán)格安全傳輸践盼,導(dǎo)致服務(wù)器要求瀏覽器轉(zhuǎn)跳到HTTPS協(xié)議的地址鸦采,這也導(dǎo)致了瀏覽器阻止了CORS請求。
那么如果還想實現(xiàn)跨域請求咕幻,就只能把Nginx的HSTS關(guān)閉了渔伯。
找到Nginx的對應(yīng)網(wǎng)站的443端口的配置文件,找到類似以下的配置:
add_header Strict-Transport-Security max-age=31536000;
把它改成:
add_header Strict-Transport-Security max-age=0;
重啟Nginx服務(wù)器肄程,清除瀏覽器緩存(瀏覽器會緩存redirect請求)锣吼,再次請求,服務(wù)器便不再返回307要求轉(zhuǎn)跳到HTTPS協(xié)議的網(wǎng)站啦蓝厌。
注意玄叠,要修改的是443端口(即HTTPS協(xié)議)的配置文件,因為:
The
Strict-Transport-Security
header is ignored by the browser when your site is accessed using HTTP; this is because an attacker may intercept HTTP connections and inject the header or remove it. When your site is accessed over HTTPS with no certificate errors, the browser knows your site is HTTPS capable and will honor theStrict-Transport-Security
header.