談談CORS那點事

找抽的小陀螺發表於2017-09-25

前端開發過程中常常需要進行跨域請求 說跨域 有個名詞來簡單瞭解下 "同源策略"

同源策略:限制從一個源載入的文件或指令碼如何與來自另一個源的資源進行互動。這是一個用於隔離潛在惡意檔案的關鍵的安全機制。

如果協議,埠(如果指定了一個)和域名對於兩個頁面是相同的,則兩個頁面具有相同的源。

下表給出了相對baidu.com/dir/page.ht…:

  1. (同協議 同域名) baidu.com/dir/page1.h… 同 源
  2. (不同協議) baidu.com/dir/page1.h… 不同源
  3. (不同埠) baidu.com:81/dir/page1.h… 不同源
  4. (不同域名) baidu2.com/dir/page.ht… 不同源

跨域就跟在自己(同源)的家 一樣想幹啥就幹啥 可以別人家(不同源)就不行了
這時候我就想要訪問不同源的 以往的幹法是
JSONP是可以實現的 但是有幾個不好的地方

  1. JSONP只能實現GET請求
  2. JSONP被老的瀏覽器支援

這個時候cors出現了
CORS:跨域資源共享(CORS )是一種網路瀏覽器的技術規範,它為Web伺服器定義了一種方式,允許網頁從不同的域訪問其資源。而這種訪問是被同源策略所禁止的。CORS系統定義了一種瀏覽器和伺服器互動的方式來確定是否允許跨域請求。 它是一個妥協,有更大的靈活性,但比起簡單地允許所有這些的要求來說更加安全。

所以按照這麼說 這CORS就是一種規範 只有基於這個規範 按照規矩來就可以實現不同源之間資源訪問

各主流的瀏覽器都會對動態的跨域請求進行特殊的驗證處理。驗證處理分為簡單請求驗證處理和預先請求驗證處理。

簡單請求:
當請求同時滿足下面兩個條件時候

請求方法是下列之一:

  • GET
  • HEAD
  • POST

請求頭中的Content-Type請求頭的值是下列之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

簡單請求時候 瀏覽器會直接傳送跨域請求在請求頭中攜帶Origin的header表明這是一個跨域的請求。伺服器端接到請求後,會根據自己的跨域規則,通過Access-Control-Allow-Origin和Access-Control-Allow-Methods響應頭,來返回驗證結果。

Access-Control-Allow-Origin: http://XXX.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8複製程式碼

這裡是允許訪問後伺服器響應
來解釋下

  • Access-Control-Allow-Origin: 要麼指定 origin值 要麼就是* 表示接受任意域名請求
  • Access-Control-Allow-Credentials: 該欄位可選。它的值是一個布林值,表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中。設為true,即表示伺服器明確許可,Cookie可以包含在請求中,一起發給伺服器。這個值也只能設為true,如果伺服器不要瀏覽器傳送Cookie,刪除該欄位即可。

如果要傳送Cookie,Access-Control-Allow-Origin就不能設為星號,必須指定明確的、與請求網頁一致的域名。同時,Cookie依然遵循同源政策,只有用伺服器域名設定的Cookie才會上傳,其他域名的Cookie並不會上傳,且(跨源)原網頁程式碼中的document.cookie也無法讀取伺服器域名下的Cookie。

預先請求
當請求同時滿足下面兩個條件時候

請求方法不是下列之一:

  • GET
  • HEAD
  • POST

請求頭中的Content-Type請求頭的值不是下列之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

預先請求 瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些HTTP動詞和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。

下面是預先請求的HTTP頭資訊

OPTIONS /cors HTTP/1.1
Origin: http://xxx.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...複製程式碼

"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問的。頭資訊裡面,關鍵欄位是Origin,表示請求來自哪個源。
上面預先請求中

  • Access-Control-Request-Method: 表示請求的用到那個HTTP方法
  • Access-Control-Request-Headers:該欄位是一個逗號分隔的字串,指定瀏覽器CORS請求會額外傳送的頭資訊欄位,上例是X-Custom-Header。

下面是預先請求響應

Access-Control-Allow-Origin: http://xxx.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header複製程式碼
  • Access-Control-Allow-Origin:表示xxx.com可以請求資料。該欄位也可以設為星號,表示同意任意跨源請求。

一旦伺服器通過了"預檢"請求,以後每次瀏覽器正常的CORS請求,就都跟簡單請求一樣,會有一個Origin頭資訊欄位。伺服器的迴應,也都會有一個Access-Control-Allow-Origin頭資訊欄位。

參考連結: 跨域資源共享 CORS 詳解

相關文章