CORS 是一個 W3C 標準,全稱是「跨域資源共享」(Cross-origin resource sharing)。api
默認瀏覽器爲了安全,遵循「同源策略」,不容許 Ajax 跨域訪問資源,而爲了容許這種操做,服務器端和客戶端都要遵循一些約定。跨域
服務器端需設置如下響應頭:瀏覽器
Access-Control-Allow-Origin: <origin> | * // 受權的訪問源 Access-Control-Max-Age: <delta-seconds> // 預檢受權的有效期,單位:秒 Access-Control-Allow-Credentials: true | false // 是否容許攜帶 Cookie Access-Control-Allow-Methods: <method>[, <method>]* // 容許的請求動詞 Access-Control-Allow-Headers: <field-name>[, <field-name>]* // 額外容許攜帶的請求頭 Access-Control-Expose-Headers: <field-name>[, <field-name>]* // 額外容許訪問的響應頭
咱們看到,Access-Control-Allow-Credentials
響應頭會使瀏覽器容許在 Ajax 訪問時攜帶 Cookie,但咱們仍然須要對 XMLHttpRequest 設置其 withCredentials
參數,才能實現攜帶 Cookie 的目標。安全
示例代碼以下:服務器
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
注意,爲了安全,標準裏不容許 Access-Control-Allow-Origin: *
,必須指定明確的、與請求網頁一致的域名。同時,Cookie 依然遵循「同源策略」,只有用目標服務器域名設置的 Cookie 纔會上傳,並且使用 document.cookie
也沒法讀取目標服務器域名下的 Cookie。cookie
下面簡單普及一下 CORS 的有關知識。app
瀏覽器對待 CORS 有兩種規則,一種只有一次請求,一種要多發送一次「預檢查」請求。url
同時知足如下條件:code
動詞限制,只容許是:orm
HEAD
GET
POST
請求頭限制,只容許出現:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
且只容許是:
application/x-www-form-urlencoded
multipart/form-data
text/plain
簡單請求瀏覽器會直接發送該請求,並附加 Origin
頭,好比:
Origin: localhost:8080
服務器會返回:
Access-Control-Allow-Origin: http://localhost:8080 Access-Control-Max-Age: 600 Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: X-Custom-Header
瀏覽器在收到服務器返回時,先檢查是否容許訪問,不容許則直接報錯(可用 XMLHttpRequest.onerror
捕獲)。
不知足簡單 CORS 要求的請求,在正式請求前,瀏覽器會發送一次 OPTIONS
動詞的請求。
例如欲請求 PUT /xxx
,想額外發送 X-Custom-Header
頭,則會先發送:
OPTIONS /xxx HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: localhost:8080
服務器返回:
HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: X-Custom-Header Access-Control-Allow-Methods: PUT Access-Control-Allow-Origin: http://localhost:8080 Access-Control-Max-Age:600 Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH Vary: Origin
瀏覽器檢查完,一切順利,才發送真正的請求。