Access-Ctrol-Allow-Headers:*兼容問題導致的跨域失敗

現象:

通過抓包看到在部分客戶端上跨域的非簡單請求只發送一個預檢的OPTIONS請求,之後的真實請求並沒有發送。

出現問題的環境:

部分IOS低版本系統。

windows系統微信內必現(2020-04-29)。

分析

通過上面條件OPTIONS請求發送成功,但是實際請求沒有發送,可以推斷出是服務端相關HTTP頭沒有設置正確,導致客戶端認爲服務端不允許當前源上的web應用跨域訪問該資源,所以後面真正的請求沒有發送(fetch的表現爲status: 0)。

服務端響應頭如下:

Access-Control-Allow-Origin: * 
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *

正常來說不存在問題,因爲設置的值也都是合法的,並且在絕大部分客戶端上都是正常的。

CORS定義:

CORS跨域資源共享,是通過額外的HTTP頭告訴瀏覽器,源上的web應用被允許訪問來自不同源服務器的指定資源。

這裏額外的HTTP頭值得注意,可以看出來CORS在不同的瀏覽器上可能是有兼容性問題。

方案

一開始的猜想是HTTP請求的method的值OPTIONS被客戶端錯誤設置爲小寫,導致服務端異常。但是通過抓包看到OPTIONS請求正確返回(status: 204),並且後端日誌中並未收到小寫的OPTIONS請求。所以這個排除。

然後着眼於服務端返回的相關HTTP頭

Access-Control-Allow-Origin: * 
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *

本地復現出來,並排查是因爲Access-Control-Allow-Headers: * 導致的,這個屬性有某些兼容性問題。

Access_Control_Allow_Headers: *

MDN中介紹 Access-Control-Allow-Headers: * 有兩重意思。

一個是在服務端設置Access-Control-Allow-Credentials: true的時候這個 * 只會被客戶端當做字符串 * (我們不希望的,會出錯的)。

另一個是沒有這個設置則會被當做通配符(我們希望的,不會出錯的)。

當然這裏響應頭中並沒有Access-Control-Allow-Credentials: true設置,但還是出錯了。

猜測是客戶端對於 * 的實現上有兼容性問題,所以建議不要這樣設置,用到什麼設置什麼最好,例如:Access-Control-Allow-Headers: Content_Type。

之後成功排除了問題。

結論

Access-Control-Allow-Headers: * 在部分客戶端上有兼容問題。

注:跨域錯誤是不會暴露給JS的,就意味着 corsError.message 拿不到錯誤的具體信息,不太好在沒有控制檯的環境看到問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章