CORS,全名為跨域資源共享,是為了讓不同網站的頁面之間互相訪問數據的機制。簡單來說,CORS 的工作機制是這樣的:網站 A 請求網站 B 的資源,網站 A 發起的請求會在 Origin
請求頭上帶上自己的源(origin
)信息,如果網站 B 返回的響應頭里有Access-Control-Allow-Origin
響應頭,且響應頭的值是網站 A 的源(或者是*
),那么網站 A 就能成功訪問到這份資源,否則就報跨域錯誤。
瀏覽器在一般的 <img>
標簽下發起的就是個非 CORS 請求,而在XHR/fetch
下默認發起的就是 CORS 請求;還比如在一般的<script>
標簽下發起的是非 CORS 請求(所以才能有 jsonp),而在新的 <script type="module"中
發起的是 CORS 請求。
當我們把Access-Control-Allow-Origin
固定寫死為*或者固定的一個網站,不論請求頭里的
Origin
是什么,甚至沒有 Origin
也一樣返回那個值,我們稱這時的響應為無條件型CORS響應。
條件型CORS響應有兩種情況:
1.有Origin請求頭才返回Access-Control-Allow-Origin
響應頭,沒有就不返回
2.設置*.taobao.com,當一級域名不同時就不返回
條件型CORS會遇到這樣一種場景:在同一個瀏覽器下,先打開了foo.taobao.com
上的一個頁面,訪問了我們的資源,這個資源被瀏覽器緩存了下來,和資源內容一起緩存的還有Access-Control-Allow-Origin: https://foo.taobao.com
響應頭。這時又打開 bar.taobao.com
上的一個頁面,這個頁面也要訪問那個資源,這時它會讀取本地緩存,讀到的 Access-Control-Allow-Origin
頭是緩存下的 https://foo.taobao.com
而不是自己想要的 https://bar.taobao.com
,這時就報跨域錯誤了,雖然它應該是能訪問到這份資源的。
這時我們設置Vary: Origin 讓同一個 URL 有多份緩存,這樣通過不同的方式進行請求,origin不同就不會調用緩存,也就不會遇到跨域問題了。