聊聊CORS的那些事兒

CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。當兩個地址scheme+host+port不一樣的時候,就是不一樣域的地址。html

1. 爲何有CORS

cors是瀏覽器的策略,目的是爲了保證網絡上資源調用的安全性。若是瀏覽器僅僅是訪問資源,不會存在跨域問題,好比訪問圖片,JS等文件;可是若是是讀取元數據,就會受到瀏覽器CORS的限制,好比AJAX請求。前端

2. CORS請求類型

瀏覽器將CORS請求分紅兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。web

  • 請求方法是如下三種方法之一:HEAD,GET,POST
  • HTTP的頭信息不超出如下幾種字段:Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type: 只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

知足以上條件的爲簡單請求,不然爲非簡單請求(好比常見的自定義header字段,或是Content-Type:application/json等)。json

2.1 簡單請求

對於簡單請求,瀏覽器發送請求時會在request header裏添加Origin字段,標記請求源。服務器處理請求後,返回響應信息,瀏覽器檢查響應信息,發現響應頭裏沒有設置Access-Control-Allow-Origin等跨域信息,會攔截請求,並拋出錯誤。跨域

2.2 非簡單請求

非簡單跨域請求在發送時,瀏覽器會增長一個options預檢請求。大概流程以下:瀏覽器

  • 瀏覽器發送一個post請求,請求頭裏添加過自定義字段
  • 瀏覽器發現是個非簡單請求,會先發一個options的預檢請求(prefight request)
  • 預檢請求裏瀏覽器會檢查服務器端返回的response,若是response裏添加過跨域字段,則預檢請求經過
  • 瀏覽器再發送真實的post請求

請求頭設置自定義字段

當非簡單請求裏添加過自定義請求頭字段,則 response 裏須要同步設置 Access-Control-Allow-Headers: '自定義header字段名',此時預檢請求才會校驗經過。緩存

// Request
headers: {
  'Content-Type': 'application/json',
  'system': 'web',
  'version': 'v1.0'
}
複製代碼
// Response
'Access-Control-Allow-Headers': 'Content-Type, system, version'
複製代碼

跨域獲取cookie

跨域讀取cookie, 須要知足以下三個條件:安全

  • 客戶端設置 withCredentials: true(credentials:'include'),表示贊成發送cookie
  • 服務端設置 Access-Control-Allow-Credentials: true,表示贊成接收cookie
  • Access-Control-Allow-Origin 指定固定域名

前端讀取響應頭header字段

通常前端只能讀取resopnse body,若是想要讀取自定義的response header信息,就須要設置Access-Control-Expose-Headers字段,指定須要暴露出去的header字段,這樣前端就能夠經過JS來讀取響應頭裏的header信息了。服務器

// js
let system = response.headers.get('system');
複製代碼
// response
Access-Control-Expose-Headers: 'system'
複製代碼

支持GET、HEAD,POST以外的請求類型

若是某個請求類型是delete,則響應頭裏須要設置Access-Control-Allow-Methods字段。markdown

// response
Access-Control-Allow-Methods: 'delete'
複製代碼

緩存預檢請求

可使用 Access-Control-Max-Age 設置預檢請求的有效期。在這段時間內,同個請求的預檢請求只會請求一次。

// response
Access-Control-Max-Age: 100  // 100秒內使用緩存過的預檢請求
複製代碼

3. 跨域頭設置

3.1 Access-Control-Allow-Origin

值爲 * 或是固定的域名,表示容許跨域請求的域名。

3.2 Access-Control-Allow-Credentials

值爲 true/false,表示服務器是否接收Cookie。想要跨域傳遞cookie,除了服務端Access-Control-Allow-Credentials: true接收cookie外;客戶端請求也須要設置withCredentials: true,表示瀏覽器贊成發送cookie。另外 Access-Control-Allow-Origin 必須是個指定的域名。

3.3 Access-Control-Allow-Headers

值爲請求頭裏設置的自定義header字段。

3.4 Access-Control-Expose-Headers

值爲須要暴露出去的header字段。

3.5 Access-Control-Allow-Methods

跨來源的請求只接受三種類型GET、HEAD,POST。除此以外,若是是其它請求類型,則響應頭裏須要設置Access-Control-Allow-Methods: 'xxx'。

3.6 Access-Control-Max-Age

Access-Control-Max-Age 指定本次預檢請求的有效期,單位是秒。

參考資料

www.ruanyifeng.com/blog/2016/0…

mp.weixin.qq.com/s/y8e1HLNzb…

相關文章
相關標籤/搜索