什么是跨域
CORS: Cross-Origin Resource Sharing,即跨域資源共享。從安全的角度考慮,瀏覽器限制了從腳本內(nèi)部發(fā)起跨域請求。也就是說,部分HTML標簽發(fā)起的資源請求未做限制(link、script、a、img...)。由此也可以知道,跨域是瀏覽器的安全措施,與http請求是無關(guān)的。
什么時候會發(fā)生跨域
當(dāng)請求資源的URL與當(dāng)前腳本所處的URL不同時,就會發(fā)生跨域,不同之處包括三個方面的不同(protocol協(xié)議,domain域名,port端口)。
舉例說明:在
http://localhost:8080/index.js
這個文件中發(fā)起了一個請求,相應(yīng)的URL為
1. http://www.baidu.com/path/to/resource
2. ftp://localhost:8080/path/to/resource
3. http://localhost:8081/path/to/resource
這三個URL分別對應(yīng)了三種不同的、會產(chǎn)生跨域請求的原因,域名不同、協(xié)議不同、端口不同。需要注意的是,資源路徑本身不會帶來跨域。
跨域請求的類型
簡單請求
簡單請求(Simple requests)需同時滿足的條件:
1. 請求方法是能是:GET HEAD POST
2. Fetch 規(guī)范定義了對 CORS 安全的首部字段集合,不得人為設(shè)置該集合之外的其他首部字段。該集合為:
? ? Accept
? ? Accept-Language
? ? Content-Language
? ? Content-Type (需要注意額外的限制)
? ? DPR
? ? Downlink
? ? Save-Data
? ? Viewport-Width
? ? Width
3. Content-Type 的值僅限于下列三者之一:
? ? text/plain
? ? multipart/form-data
? ? application/x-www-form-urlencoded
4. 請求中的任意XMLHttpRequestUpload 對象均沒有注冊任何事件監(jiān)聽器;
? ? XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問。
5. 請求中沒有使用 ReadableStream 對象。
預(yù)檢請求
對那些可能對服務(wù)器數(shù)據(jù)產(chǎn)生副作的 HTTP 請求方法(特別是 GET 以外的 HTTP 請求,或者搭配某些 MIME 類型的 POST 請求),瀏覽器必須首先使用 OPTIONS 方法發(fā)起一個預(yù)檢請求(preflight request),從而獲知服務(wù)端是否允許該跨域請求。
需預(yù)檢的請求(Preflighted requests)要求必須首先使用 OPTIONS 方法發(fā)起一個預(yù)檢請求到服務(wù)器,以獲知服務(wù)器是否允許該實際請求。
當(dāng)請求滿足下述任一條件時,即應(yīng)首先發(fā)送預(yù)檢請求:
1. 使用了下面任一 HTTP 方法:
? ? PUT
? ? DELETE
? ? CONNECT
? ? OPTIONS
? ? TRACE
? ? PATCH
2. 人為設(shè)置了對 CORS 安全的首部字段集合之外的其他首部字段。該集合為:
? ? Accept
? ? Accept-Language
? ? Content-Language
? ? Content-Type (需要注意額外的限制)
? ? DPR
? ? Downlink
? ? Save-Data
? ? Viewport-Width
? ? Width
3. Content-Type 的值不屬于下列之一:
? ? application/x-www-form-urlencoded
? ? multipart/form-data
? ? text/plain
4. 請求中的XMLHttpRequestUpload 對象注冊了任意多個事件監(jiān)聽器。
5. 請求中使用了ReadableStream對象。
帶權(quán)限的請求(Requests with credentials)
一般而言,對于會跨域的XMLHttpRequest 或 Fetch 請求,瀏覽器不會發(fā)送身份憑證信息。對于附帶身份憑證的請求,服務(wù)器不得設(shè)置 Access-Control-Allow-Origin 的值為“*”。
與跨域相關(guān)的請求頭和響應(yīng)頭
Request Headers
? ? Origin
? ? Access-Control-Request-Method
? ? Access-Control-Request-Headers
Response Headers
? ? Access-Control-Allow-Origin
? ? Access-Control-Expose-Headers
? ? Access-Control-Max-Age:表明該響應(yīng)的有效時間,在有效時間內(nèi),瀏覽器無須為同一請求再次發(fā)起預(yù)檢請求。
? ? Access-Control-Allow-Credentials
? ? Access-Control-Allow-Methods
? ? Access-Control-Allow-Headers