標籤:

跨域——CORS詳解

CORS(Cross-origin resource sharing) 「跨域資源共享」

在出現CORS標準之前, 我們還只能通過jsonp(jsonp跨域請求詳解)的形式去向「跨源」伺服器去發送 XMLHttpRequest 請求,這種方式吃力不討好,在請求方與接收方都需要做處理,而且請求的方式僅僅局限於GET。所以 ,CORS標準必然是大勢所趨,並且市場上絕大多數瀏覽器都已經支持CORS。(IE10以上)

CORS概念

支持CORS請求的瀏覽器一旦發現ajax請求跨域,會對請求做一些特殊處理,對於已經實現CORS介面的服務端,接受請求,並做出回應。

有一種情況比較特殊,如果我們發送的跨域請求為「非簡單請求」,瀏覽器會在發出此請求之前首先發送一個請求類型為OPTIONS的「預檢請求」,驗證請求源是否為服務端允許源,這些對於開發這來說是感覺不到的,由瀏覽器代理。

總而言之,客戶端不需要對跨域請求做任何特殊處理。

簡單請求與非簡單請求

瀏覽器對跨域請求區分為「簡單請求」與「非簡單請求」

「簡單請求」滿足以下特徵:

(1) 請求方法是以下三種方法之一: HEAD GET POST(2)HTTP的頭信息不超出以下幾種欄位: Accept Accept-Language Content-Language Last-Event-ID Content-Type: application/x-www-form-urlencoded、 multipart/form-data、text/plain

不滿足這些特徵的請求稱為「非簡單請求」,例如:content-type=applicaiton/json , method = PUT/DELETE...

簡單請求

瀏覽器判斷跨域為簡單請求時候,會在Request Header中添加 Origin (協議 + 域名 + 埠)欄位 , 它表示我們的請求源,CORS服務端會將該欄位作為跨源標誌。

CORS接收到此次請求後 , 首先會判斷Origin是否在允許源(由服務端決定)範圍之內,如果驗證通過,服務端會在Response Header 添加 Access-Control-Allow-Origin、Access-Control-Allow-Credentials等欄位。

必須欄位Access-Control-Allow-Origin表示服務端允許的請求源*標識任何外域多個源 , 分隔可選欄位Access-Control-Allow-Credentialsfalse 表示是否允許發送Cookie設置為true 同時ajax請求設置withCredentials = true,瀏覽 器的cookie就能發送到服務端Access-Control-Expose-Headers調用getResponseHeader()方法時候能從header中獲 取的參數

瀏覽器收到Respnose後會判斷自己的源是否存在 Access-Control-Allow-Origin允許源中,如果不存在,會拋出「同源檢測異常」。

總結:簡單請求只需要CORS服務端在接受到攜帶Origin欄位的跨域請求後,在response header中添加Access-Control-Allow-Origin等欄位給瀏覽器做同源判斷。

非簡單請求

進行非簡單請求時候 , 瀏覽器會首先發出類型為OPTIONS的「預檢請求」,請求地址相同 ,

CORS服務端對「預檢請求」處理,並對Response Header添加驗證欄位,客戶端接受到預檢請求的返回值進行一次請求預判斷,驗證通過後,主請求發起。

例如:發起 content-type=application/json 的非簡單請求,這時候傳參要注意為json字元串

這裡可以看到,瀏覽器連續發送了兩個jsonp.do請求 , 第一個就是「預檢請求」,類型為OPTIONS,因為我們設置了content-type這個屬性,所以預檢請求的Access-Control-Expose-Headers必須攜帶content-type,否則預檢會失敗。

預檢通過後,主請求與簡單請求一致。

總結:非簡單請求需要CORS服務端對OPTIONS類型的請求做處理,其他與簡單請求一致

Spring MVC CORS

通過上面敘述,我們得知藉助CORS我們不必關心發出的請求是否跨域,瀏覽器會幫我們處理這些事情,但是服務端需要支持CORS,服務端實現CORS的原理也很簡單,在服務端完全可以對請求做上下文處理,已達到介面允許跨域訪問的目的。

當然,也有很多第三方的CORS插件,例如:Spring MVC 在4.2以上版本也支持了CORS配置,這樣,服務端也無需自己操心了!

相關文檔

跨域資源共享 CORS 詳解 - 阮一峰的網路日誌

SpringMvc解決跨域問題 - 王念博客 - 開源中國社區


推薦閱讀:

流式處理對 請求/響應 正文數據體的影響
為什麼fiddler無法抓到訊飛語音輸入的請求?
優雅地請求: fetch, node-fetch, isomorphic-fetch
HTML5的Websocket(理論篇 I)
http協議請求響應頭中參數的疑問??

TAG:Spring | Ajax | HTTP |