瀏覽器端CORS策略+快取策略導致的跨域策略失效問題

literal發表於2017-10-23

問題現象

DataV的螢幕上發現了這麼個詭異的現象:

在開發的螢幕中,用xhr載入圖片供canvas渲染,時好時壞,報錯的異常是:跨域失敗,檢視network的請求,在失敗的時候,圖片返回的header裡確實缺失了cors的幾個關鍵資訊。

而且開發的同學經常是好的,到了使用者手裡就不行。

伺服器端的oss策略仔細檢查了,沒有問題, 而且螢幕上有時候是好的,說明服務至少正常過。oss的介面冪等基本上不用懷疑,所以把疑問再次轉回到客戶端。

在一次本地重現之後,在network裡過濾出錯圖片地址,結果發現除了 xhr的請求,還有一個標籤發起的請求, 把偵錯程式的快取關閉之後,重新整理螢幕頁面,重現了。

故障原因

上述頁面有兩個請求指向同一個 圖片地址, 當img標籤先行的時候,

<img src="pic.png"/>

瀏覽器返回了圖片,但是由於img標籤發起請求的時候並不會帶上 Origin頭,所以Aliyun OSS在返回的response header 裡並沒有帶上 cors需要的 Access-Control-Allow-Origin 等資訊,因為 標籤並不受同源策略限制。 於是瀏覽器 cache了這個圖片請求,當然也包括header資訊。

當 xhr再次發起對這個圖片的請求時,命中了瀏覽器快取,這時候問題就出現了,header裡沒有告訴xhr可以信任當前域,所以瀏覽器拒絕了這個請求。

解決辦法

最簡單的辦法,把兩個呼叫地址區分開,xhr可以加個 ?xhr

所以這種異常,不是OSS的鍋

瀏覽器需要改進麼?

目前瀏覽器快取策略只是根據資源地址來cache,並沒有區分呼叫形式,以及呼叫時header的差異。
作為資源cache,也合情合理。

不過歷史原因, 圖片資源、script標籤 等,瀏覽器一直沒有對這些請求開啟同源策略限制,當然也無法開啟(一旦大量的站點要掛)。

有沒有必要開啟? 能不能開啟? 這是另外的問題,但是Origin的頭可以先帶上。


相關文章