CORS

LeoYao發表於2020-07-13

CORS 需要瀏覽器和伺服器同時支援。目前,所有瀏覽器都支援該功能。
整個 CORS 通訊過程,都有瀏覽器自動完成,使用者無感知,對開發者而言,CORS 和 AJAX 通訊無異,前端程式碼完全一樣。瀏覽器如果發現 AJAX 請求跨域,會自動新增一些附加的頭資訊,如果是非簡單請求,會多出一次 OPTION 請求。實現 CORS 通訊的關鍵是伺服器。只要伺服器實現了 CORS 介面,就可以跨域通訊。

簡單請求兩大條件

請求方法屬於以下三種方式之一

  • HEAD
  • GET
  • POST

HTTP 的頭資訊不超出以下幾種欄位

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限於三個值 application/x-www-urlencodemultipart/form-datatext/plain

簡而言之,簡單請求就是簡單的 HTTP 方法和簡單的 HTTP 頭資訊的結合
其實簡單請求就是傳統的表單請求,規避 CORS 的限制

簡單請求

基本流程

瀏覽器自動在頭資訊中新增一個 Origin 欄位,說明本次請求來源哪個域(協議+域名+埠),伺服器會根據這個值,決定是否同意本次請求。
如果 Origin 指定的源,不在許可範圍內,伺服器會返回一個正常的 HTTP 響應,但響應的頭資訊不包含 Access-Control-Allow-Origin 欄位

withCredentials 屬性

CORS 請求預設不包含 Cookie 資訊(以及 HTTP 認證資訊等),這是為了降低 CSRF 攻擊的風險。如果伺服器需要拿到 Cookie,這時需要伺服器顯式指定 Access-Control-Allow-Credentials 欄位,告訴瀏覽器可以傳送 Cookie

Access-Control-Allow-Credentials: true

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

非簡單請求

預檢請求

非簡單請求是對伺服器提出特殊要求的請求,比如請求方法是 PUTDELETE,或者 Content-Type 欄位的型別是 application/json

非簡單請求的 CORS 請求,會在正式通訊之前,增加一次 HTTP 查詢請求,即預檢請求。詢問當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些 HTTP 方法和頭資訊欄位。只有得到肯定回覆,瀏覽器才會發出正式的 XMLHttpRequest 請求,否則報錯

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章