是由W3C提出的一個用於瀏覽器以XMLHttpRequest方式向其餘源的服務器發起請求的規範。不一樣於JSONP,CORS是以Ajax方式進行跨域請求,須要服務端與客戶端的同時支持。目前CORS在絕大部分現代瀏覽器中都是支持的(IE瀏覽器不能低於10)html
CORS標準定義了一個規範的HTTPHeaders來使得瀏覽器與服務端之間能夠進行協商來肯定某個資源是否能夠由其餘域的客戶端請求得到。儘管不少的驗證與鑑權是由服務端完成,可是本質上大部分的檢查和限制仍是應該由瀏覽器完成。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。通常來講CORS會分爲簡單請求與預檢請求兩大類。api
當瀏覽器的請求方式知足如下的任意一個條件的時候,瀏覽器會先發送一個OPTION請求,用來與目標域名服務器協商決定是否能夠發送實際的跨域請求。OPTIONS請求頭部中會包含如下頭部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。
服務器收到OPTIONS請求後,設置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers頭部與瀏覽器溝通來判斷是否容許這個請求。跨域
請求方法不是下列之一:瀏覽器
請求頭中的Content-Type請求頭的值不是下列之一:緩存
不然就是預檢請求。預檢請求會在正式通訊以前,增長一次HTTP查詢請求。瀏覽器會先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。預檢請求的發送請求:服務器
"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問的。請求頭信息裏面,關鍵字段是Origin,表示請求來自哪一個源。
除了Origin字段,"預檢"請求的頭信息包括兩個特殊字段:cookie
預檢請求的返回:app
一旦服務器經過了預檢請求,之後每次瀏覽器正常的CORS請求,就都跟簡單請求同樣,會有一個Origin頭信息字段。服務器的迴應,也都會有一個Access-Control-Allow-Origin頭信息字段。cors
當瀏覽器的請求方式是HEAD、GET或者POST,而且HTTP的頭信息中不會超出如下字段:url
瀏覽器會將該請求定義爲簡單請求,對於簡單的跨域請求或者經過了預檢的請求,瀏覽器會自動在請求的頭信息加上Origin字段,表示本次請求來自哪一個源(協議 + 域名 + 端口),即代表這是一個跨域請求。服務端會獲取到這個值,根據相應的跨域規則而後判斷是否贊成此次請求並返回。典型的請求頭尾:
// 請求 - GET /cors HTTP/1.1 - Origin: http://localhost:8080 - Host: api.alice.com - Accept-Language: en-US - Connection: keep-alive - User-Agent: Mozilla/5.0...
若是服務端容許,在返回的頭信息中會多出幾個字段:
// 返回 Access-Control-Allow-Origin: http://localhost:8080 Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: Info Content-Type: text/html; charset=utf-8
須要注意的是,若是要發送Cookie,Access-Control-Allow-Origin就不能設爲*,必須指定明確的、與請求網頁一致的域名。同時,Cookie依然遵循同源政策,只有用服務器域名設置的Cookie纔會上傳,其餘域名的Cookie並不會上傳,且原網頁代碼中的document.cookie也沒法讀取服務器域名下的Cookie。
若是服務端拒絕了調用,即不會帶上 Access-Control-Allow-Origin 字段,瀏覽器發現這個跨域請求的返回頭信息沒有該字段,就會拋出一個錯誤,會被 XMLHttpRequest 的 onerror 回調捕獲到。這種錯誤沒法經過 HTTP 狀態碼判斷,由於迴應的狀態碼有多是200。
服務器端對於跨域請求的處理流程以下: