CORS前奏
瞭解CORS跨域之前,也許我們還應該對跨域這麼個東東的一些概念要有些瞭解。
1. 什麼是跨域
廣義上的跨域是指一個 域下的文件或指令碼試圖去請求另一個域下的資源。比如: 資源跳轉(a連結)、資源嵌入(link, script)、指令碼請求(js發起ajax請求)等。而我們通常所討論的跨域是指的是狹義上的跨域,指的是由瀏覽器同源策略限制的一類請求場景。那麼什麼是同源策略,同源策略又限制了什麼。
2. 什麼是同源策略
同源指的是如果兩個頁面的協議,埠和域名都相同,則兩個頁面具有相同的源,只要其中之一不同,則那這兩個源就不相同。
3. 同源策略限制了什麼
- Cookie、LocalStorage 和 IndexDB 無法讀取。
- DOM 無法獲得(內嵌iframe中,父子頁面不能獲取DOM)。
- AJAX 請求不能傳送。
4. 為什麼有同源策略的限制
同源政策的目的,是為了保證使用者資訊的安全,防止惡意的網站竊取資料。
- Cookie、LocalStorage 和 IndexDB 無法讀取限制。(原因比如:訪問一個惡意網站,獲取到所有網站下的cookie資訊, 如果有某個已登入的網站, 登入驗證放在cookie裡, 那就可以偽裝你的身份去訪問該 網站。)
- DOM 無法獲得(內嵌iframe中,父子頁面不能獲取DOM)。(原因比如:一個惡意 網站,iframe嵌入一個正規網站的, 這樣就可以獲取到使用者的登入資訊和密碼。 )
- AJAX 請求不能傳送。 (原因比如: 沒限制直接就可以用指令碼把伺服器給打爆了。)
5. 解決跨域的方法
- JSONP
- location.hash
- document.domain
- window.name
- window.postMessage
- WebSocket
- CORS 接下來要重點討論下的是CORS是如何解決ajax請求跨域的。
CORS正文
CORS(跨域資源共享)是一種機制,允許 Web 應用伺服器進行跨域訪問控制,從而使跨域資料傳輸得以安全進行。CORS的使用要瀏覽器和服務端同時支援,並配合使用, IE要大於10。
1. 怎麼工作的
js中進行一個跨域的ajax請求,瀏覽器判斷該請求是簡單請求還是複雜請求,簡單請求就直接傳送, 複雜請求就先傳送一次預檢請求, 預檢請求成功後, 再傳送完整的請求, 整個過程對使用者是無感知的。那麼什麼是簡單請求和複雜請求呢?2. CORS的簡單請求和複雜請求
簡單請求需要同時滿足以下兩個條件:
- 請求是以下方法之一: GET、HEAD、POST
- 不得人為設定以下集合之外的其他首部欄位:
Accept
Accept-Language
Content-Language
Content-Type (需要注意額外的限制):
(text/plain
multipart/form-data
application/x-www-form-urlencoded)
複製程式碼
非簡單請求就認為是複雜請求(比如PUT、DELETE請求, content-type設定為appliction/json等), 就需要傳送預檢請求。
3. CORS是如何工作的(如何確定是否允許跨域)
確定是否允許跨域就需要瀏覽器和伺服器共同協作完成,主要就是通過特定的一些響應頭來完成。預檢請求還需要有特定的請求頭。那麼特定請求頭分別有哪些以及是如何配合使用的。
######a. 服務端響應頭
- Access-Control-Allow-Origin:這個欄位是必須的,代表的是允許跨域的源, '*'代表任意的源。
- Access-Control-Allow-Methods: 這個欄位也是必須的, 代表允許跨域的http請求方法。
- Access-Control-Allow-Credentials: 非必須的, 表示是否允許傳送cookie, 預設是false,如果設定為true則同時還需要客戶端要設定xhr.withCredentials = true才能起作用, 兩者是共存的(其中的cookie帶的是目標域的cookie)。
- Access-Control-Allow-Headers: 非必須的,表示允許的請求頭, 如果預檢請求中包括了Access-Control-Request-Headers, 則服務端必須設定該欄位。
- Access-Control-Max-Age:非必須的,用來指定本次預檢請求的有效期,單位為秒。即將CORS的響應配置快取在瀏覽器端, 在快取生效時間內,下次請求不用傳送預檢請求。 需要注意的是: 瀏覽器的disable-cache要關掉
- Access-Control-Expose-Headers:可選欄位, 客戶端只能根據響應獲取到以下的響應頭:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
複製程式碼
如果想要獲取額外的響應頭資訊, 則需要將其設定在這個欄位中。
b. 客戶端預檢請求頭
- Access-Control-Request-Method: 該欄位是必須的,用來表示覽器的CORS請求會用到哪個HTTP方法。
- Access-Control-Request-Headers: 該欄位是非必須的,指定瀏覽器CORS請求額外傳送的頭資訊欄位。
針對簡單請求情況:
不會傳送預檢請求, 直接是發起真正的請求,只要 Access-Control-Allow-Origin與Access-Control-Allow-Methods正確的設定就能發起請求。
具體的coding例子:github傳送門