跨域——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-Credentials:false 表示是否允許發送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協議請求響應頭中參數的疑問??