若請求的url的協議、域名、端口中的任意一個與當前的url不一樣,即爲跨域請求。跨域
跨域請求使得頁面體驗更好,但同時也帶來了安全隱患。常見的一種網絡攻擊叫CSRF(Cross-site request forgery)。它的攻擊原理大體以下:瀏覽器
基於CSRF等安全隱患,瀏覽器會限制從腳本發出的跨域請求,雖然安全性更高,頁面體驗卻差了。因而W3C推出了一種跨域的訪問驗證的機制,即CORS,這種機制支持跨域請求,且跨站數據傳輸更安全。安全
CORS驗證機制須要客戶端和服務的協同處理。服務器
瀏覽器會對全部跨域請求進行驗證,分爲簡單請求驗證處理和預檢請求驗證處理。那麼對應的就有簡單請求和非簡單請求之分。cookie
簡單請求網絡
若一個請求同時知足如下兩個條件,那麼則爲簡單請求。app
對於簡單請求,瀏覽器直接發送該請求,在同一個請求中做跨域驗證。怎麼驗證呢?在請求頭上附上Origin屬性,代表這是一個跨域請求。服務器接到請求,根據設定的跨域規則來驗證,驗證經過,返回Access-Control-Allow-Origin等以Access-Control-開頭的響應頭以及請求的資源,不然返回403狀態碼,且不會返回請求的資源。fetch
非簡單請求網站
不爲簡單請求的跨域請求均爲非簡單請求。url
非簡單請求的跨域驗證經過一個預檢請求來驗證,即在發送一個正式的跨域請求以前,發送一個預檢請求,用來檢查當前網頁所在的域名是否在服務器的許可名單中以及可以使用哪些請求方法,請求頭字段。
預檢請求
若預檢請求經過驗證,則響應字段裏會包含以下字段:
Access-Control-Allow-Origin:值爲請求頭中的origin值或*
Access-Control-Allow-Methods: 代表可被支持的請求方法
Access-Control-Allow-Headers: 代表可被支持的頭信息字段
Access-Control-Allow-Credentials: 當請求要求攜帶證書信息(例如cookie,受權信息等)驗證,服務器端是否容許攜帶
Access-Control-Max-Age: 本次預檢請求的有效期,單位爲秒
若預檢請求沒經過驗證,則響應字段裏不會包含以Access-Control-開頭的響應字段,且不會發送正式的跨域請求
正式的跨域請求
與簡單請求同樣,請求頭中附帶Origin
攜帶證書信息的請求
通常狀況下,跨域請求不攜帶證書信息。但若請求的證書模式(credentials mode)被設爲include,那麼代表該請求須要攜帶證書信息。請求的證書模式可經過xmlHttpRequest.withCredentials = true設置或調用fetch([url],{mode:"include"})實現。
在簡單請求及正式的非簡單請求中,請求頭附帶證書信息,響應頭回應:Access-Control-Allow-Credentials:true,並返回請求資源。
在預檢請求中,請求頭並不會附帶證書,響應頭會迴應:Access-Control-Allow-Credentials:true。
有一點需注意:若服務器端贊成請求攜帶信息,則Access-Control-Allow-Origin不能爲*,只能爲請求頭中指定的Origin值。