> 幾個問題: 1. 什么是跨域? 2. 為什么會有跨域? 3. 如何處理跨域
我們在日常的開發中,經常會遇到跨域資源共享,或者進行跨域接口訪問的情況。跨域資源共享( CORS)機制允許 Web 應用服務器進行跨域訪問控制。
跨域資源共享標准新增了一組 HTTP 首部字段,允許服務器聲明哪些源站通過瀏覽器有權限訪問哪些資源。另外,規范要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法(特別是GET
以外的 HTTP 請求,或者搭配某些 MIME 類型的POST
請求),瀏覽器必須首先使用OPTIONS
方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。服務器確認允許之后,才發起實際的 HTTP 請求。在預檢請求的返回中,服務器端也可以通知客戶端,是否需要攜帶身份憑證(包括 Cookies和 HTTP 認證相關數據)。
在涉及到CORS的請求中,我們會把請求分為簡單請求和復雜請求。
簡單請求
滿足以下條件的請求即為簡單請求:
- 請求方法:GET、POST、HEAD
-
除了以下的請求頭字段之外,沒有自定義的請求頭
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
-
Content-Type的值只有以下三種
(Content-Type一般是指在post請求中,get請求中設置沒有實際意義)
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
-
請求中的任意XMLHttpRequestUpload 對象均沒有注冊任何事件監聽器
(未驗證)
- XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問
- 請求中沒有使用 ReadableStream 對象
(未驗證)
復雜請求
非簡單請求即為復雜請求。復雜請求我們也可以稱之為在實際進行請求之前,需要發起預檢請求的請求。
簡單請求
與復雜請求
的跨域設置
針對簡單請求,在進行CORS設置的時候,我們只需要設置
Access-Control-Allow-Origin:* // 如果只是針對某一個請求源進行設置的話,可以設置為具體的值 Access-Control-Allow-Origin: 'http://www.yourwebsite.com'
針對復雜請求,我們需要設置不同的響應頭。因為在預檢請求的時候會攜帶相應的請求頭信息
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-CUSTOMER-HEADER, Content-Type
相應的響應頭信息為:
Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type // 設置max age,瀏覽器端會進行緩存。沒有過期之前真對同一個請求只會發送一次預檢請求 Access-Control-Max-Age: 86400
如果發送的預檢請求被進行了重定向,那大多數的瀏覽器都不支持對預檢請求的重定向。我們可以通過先發送一個簡單請求的方式,獲取到重定向的url XHR.responseURL,然后再去請求這個url。
附帶身份憑證的請求
一般而言,對於跨域 XMLHttpRequest
或 Fetch 請求,瀏覽器不會發送身份憑證信息。如果要發送憑證信息,需要設置 XMLHttpRequest 的某個特殊標志位。
如果在發送請求的時候,給xhr 設置了withCredentials為true,從而向服務器發送 Cookies,如果服務端需要想客戶端也發送cookie的情況,需要服務器端也返回Access-Control-Allow-Credentials: true
響應頭信息。
對於附帶身份憑證的請求,服務器不得設置 Access-Control-Allow-Origin
的值為“*
”。
這是因為請求的首部中攜帶了Cookie
信息,如果 Access-Control-Allow-Origin
的值為“*
”,請求將會失敗。而將 Access-Control-Allow-Origin
的值設置為 http://foo.example
(請求源),則請求將成功執行。