Catagory
- Foreword
- CORS Principle
- 三個訪問控制場景
- 簡單請求
- 預請求
- 帶憑據的請求
- HTTP請求頭
- HTTP響應頭
- IE對CORS的實現
- 瀏覽器的支持
Foreword
因爲同源策略限制從一個源加載的文檔或腳本與來自另外一個源的資源進行交互。在web開發中跨域是不免的問題,或是開發時的跨域,或是線上資源請求的跨域。咱們可使用「CORS」容許跨院訪問。web
先簡單說下跨域,當一個資源請求一個其它域名或者另一個端口的資源時會產生一個跨域HTTP請求(cross-origin HTTP request)。爲了訪問資源的可靠信,會有同源策略的限制,瀏覽器會攔截跨域請求的返回結果,有些瀏覽器會更加嚴格,不容許從HTTPS的域跨域訪問HTTP,如Chrome和Firefox,這些瀏覽器在請求還未發出的時候就會攔截請求。跨域
CORS Principle
CORS(Cross-origin resource sharing,跨域資源共享)是W3C的一個工做草案,定義了在必須訪問跨域資源時,瀏覽器與服務器應該如何溝通。CORS背後的基本思想,就是使用自定義的HTTP請求頭部,讓瀏覽器和服務器進行溝通,從而決定請求或響應是應該成功,仍是失敗。
這個規範是對針對API容器的,好比 XMLHttpRequest 或者 Fetch瀏覽器
好比一個簡單的GET或者POST請求,它沒有自定義的頭部,而主題內容是text/plain。在發送請求時,須要給它附加一個額外的Oringin頭部,其中包含請求頁面的源信息(協議,域名和端口),以便服務器根據這個頭部消息來決定是否給予響應。下面是Oringin頭部的一個示例:緩存
Origin: http://www.alenqi.com安全
若是服務器認爲這個請求能夠接受,就在Access-Control-Allow-Origin頭部中返回相同的源信息。示例:服務器
Access-Control-Allow-Origin: Origin: http://www.alenqi.comcookie
若是沒有這個頭部,或者有這個頭部可是源信息不匹配,瀏覽器就會駁回請求。正常狀況下,瀏覽器會處理請求。注意,這裏的請求和響應都不包含cookie信息。app
CORS須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。 瀏覽器會自動判斷若是跨域,自動會添加一些附加的頭部信息,還有可能發送預請求。因此,若是服務端實現了響應CORS的接口,就能夠跨域訪問。cors
三個訪問控制場景
-
簡單請求
- 一些請求不會觸發 CORS preflight,而這部分在本文中被稱爲「簡單請求」。知足下述條件的就是「簡單請求」:
- 只容許下列方法:
- 除了用戶代理自動設置的頭部外,惟一容許人工設置的頭部是 Fetch 規範定義的「 CORS-safelisted request-header」,以下:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type (but note the additional requirements below)
- 容許的 Content-Type 值有:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 一個簡單的CORS頭處理的跨域請求
-
預請求
- CORS經過一種叫作preflighted Requests的透明服務器驗證機制支持開發人員使用自定義的頭部,「預請求」要求必須先發送一個 OPTIONS 方法請求給目的站點,來查明這個跨站請求對於目的站點是否是安全的可接受的。這樣作,是由於跨站請求可能會對目的站點的數據產生影響。 當請求具有如下條件,就會被當成預請求處理:
- 除了下列方法之外方法的請求:
- 除了用戶代理自動設置的頭部外,不包括一下的頭部信息,以下:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID - Content-Type (but note the additional requirements below)
- Content-Type 值有除了一下以外的:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 簡而言之,就是非簡單請求的請求就會發送預請求。
- 發送這個請求以後,服務器能夠決定是否容許這種類型的請求。服務器經過在響應中發送頭部和瀏覽器進行溝通。Preflight請求結束後,結果將按照響應頭中指定的時間緩存起來。而爲此付出的代價只是第一次發送非簡單請求時多一次HTTP請求。
-
帶憑據的請求
- 默認狀況下,跨域請求不提供(cookie,HTTP認證及客戶端SSL證實等)。經過將withCredentials屬性設置爲true,能夠指定某個請求應該發送憑據。
- 若是發送的是帶憑據的請求,可是服務器的響應中沒有包含這個頭部,那麼瀏覽器就不會把響應交給JavaScript(因而,responseText中將是空字符串,status的值爲0,並且會調用onerror()事件處理程序。另外,服務器還能夠在Preflight響應中發送這個HTTP頭部,表示容許源發送帶憑據的請求。
HTTP請求頭
Origin: <origin>
ui
Access-Control-Request-Method: <method>
Access-Control-Request-Headers: <field-name>[, <field-name>]*
HTTP響應頭
Access-Control-Allow-Origin: <origin> | *
Access-Control-Expose-Headers: X-My-Custom-Header,X-Another-Custom-Header
Access-Control-Max-Age: <delta-seconds>
Access-Control-Allow-Credentials: true | false
Access-Control-Allow-Methods: <method>[, <method>]*
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
IE對CORS的實現
- 微軟在IE8中引入了XDR(XDomainRequest)類型。這個對象與XHR相似,但能實現安全可靠的跨域通訊。XDR對象的安全機制部分實現了W3C的CORS規範。下面是XDR與XHR的一些不一樣之處:
- cookie不會隨請求發送,也不會隨響應返回
- 只能設置請求頭不信息中的Content-Type字段
- 不能訪問響應頭部信息
- 只支持GET和POST請求
- 好消息是對於CORS在IE 10中有完整的實現
瀏覽器的支持
- 拋開瀏覽器談HTTP相關規範或技術都是耍流氓。
- Desktop
- mobile