Ajax跨域的另一種實作CORS(Cross-Origin Resource Sharing),支援GET、POST、PUT、DELETE等http方法。
在我們日常的項目開發時使用AJAX,傳統的Ajax請求隻能擷取在同一個域名下面的資源,但是HTML5打破了這個限制,允許Ajax發起跨域的請求。浏覽器是可以發起跨域請求的,比如你可以外鍊一個外域的圖檔或者腳本。但是Javascript腳本是不能擷取這些資源的内容的,它隻能被浏覽器執行或渲染。主要原因還是出于安全考慮,浏覽器會限制腳本中發起的跨站請求。(同源政策, 即JavaScript或Cookie隻能通路同域下的内容)。跨域的解決方案有多重JSONP、Flash、Iframe等,當然還有CORS(跨域資源共享,Cross-Origin Resource Sharing)今天就來了解下CORS的原理,以及如何使用。
一、CORS概述
跨源資源共享标準通過新增一系列 HTTP 頭,讓伺服器能聲明那些來源可以通過浏覽器通路該伺服器上的各類資源(包括CSS、圖檔、JavaScript 腳本以及其它類資源)。另外,對那些會對伺服器資料造成破壞性影響的 HTTP 請求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些MIME類型的POST請求),标準強烈要求浏覽器必須先以 OPTIONS 請求方式發送一個預請求(preflight request),進而獲知伺服器端對跨源請求所支援 HTTP 方法。在确認伺服器允許該跨源請求的情況下,以實際的 HTTP 請求方法發送那個真正的請求。伺服器端也可以通知用戶端,是不是需要随同請求一起發送信用資訊(包括 Cookies 和 HTTP 認證相關資料)。
二、CORS原理
例如:域名A(http://a.example)的某 Web 應用程式中通過<img>标簽引入了域名B(http://b.foo)站點的某圖檔資源(http://b.foo/image.jpg)。這就是一個跨域請求,請求http報頭包含Origin: http://a.example,如果傳回的http報頭包含響應頭 Access-Control-Allow-Origin: http://a.example (或者Access-Control-Allow-Origin: http://a.example),表示域名B接受域名B下的請求,那麼這個圖檔就運作被加載。否則表示拒絕接受請求。
三、CORS跨域請求控制方法
1.http請求頭
Origin: 普通的HTTP請求也會帶有,在CORS中專門作為Origin資訊供後端比對,表明來源域。
Access-Control-Request-Method: 接下來請求的方法,例如PUT, DELETE等等
Access-Control-Request-Headers: 自定義的頭部,所有用setRequestHeader方法設定的頭部都将會以逗号隔開的形式包含在這個頭中
2.http響應頭
然後浏覽器再根據伺服器的傳回值判斷是否發送非簡單請求。簡單請求前面講過是直接發送,隻是多加一個origin字段表明跨域請求的來源。然後伺服器處理完請求之後,會再傳回結果中加上如下控制字段
Access-Control-Allow-Origin: 允許跨域通路的域,可以是一個域的清單,也可以是通配符"*"。這裡要注意Origin規則隻對域名有效,并不會對子目錄有效。即http://foo.example/subdir/ 是無效的。但是不同子域名需要分開設定,這裡的規則可以參照同源政策
Access-Control-Allow-Credentials: 是否允許請求帶有驗證資訊,XMLHttpRequest請求的withCredentials标志設定為true時,認證通過,浏覽器才将資料給腳本程式。
Access-Control-Expose-Headers: 允許腳本通路的傳回頭,請求成功後,腳本可以在XMLHttpRequest中通路這些頭的資訊
Access-Control-Max-Age: 緩存此次請求的秒數。在這個時間範圍内,所有同類型的請求都将不再發送預檢請求而是直接使用此次傳回的頭作為判斷依據,非常有用,大幅優化請求次數
Access-Control-Allow-Methods: 允許使用的請求方法,以逗号隔開
Access-Control-Allow-Headers: 允許自定義的頭部,以逗号隔開,大小寫不敏感
四、浏覽器支援情況
在大部分現代浏覽器中有所支援,支援(部分支援)CORS協定的浏覽器有IE8+, Firefox5+, Chrome12+, Safari4+,移動端幾乎全支援。

注:Internet Explorer 8 、9使用 XDomainRequest 對象實作CORS。
五、CORS使用案例
案例環境:用戶端使用jQuery,服務端WebApi(2.2)。因本人使用.net語言,是以服務端就使用webApi來示範了。
首先建立一個webApi項目,這裡就不截圖一步步介紹了,然後使用Nuget安裝支援cors的擴充元件,
Install-Package Microsoft.AspNet.WebApi.Cors
然後打開App_Start問價夾下的WebConfig.cs配置檔案類,在Register方法中配置一個全局的cors,為了友善我将一些參數配置到web.config配置檔案中
CORS WebConfig 配置
CORS 配置及啟用
如果不想使用全局的CORS,可以在某個方法或者ApiController上這樣配置:[EnableCors(origins: "*", headers: "*", methods: "*")],可以使用具體的參數,多個參數以逗号分隔,不用說,肯定英文逗号。origins 域名要帶上http的頂級域名。需要添加 using System.Web.Http.Cors;
一般請求來說,用戶端的AJAX請求不需要做任何改變,隻需要服務端稍作改變即可。
用戶端js代碼: apiRootPath是我預先設定的api的頂級域名。
因為我配置了全局的CORS方法,而且服務端沒有特别之處了,和普通的網站(不跨越)寫法一緻,這裡就不予貼出了。
如果需要對請求進行身份驗證,怎麼辦?我們一cookies實作這個驗證。
注意這個兩句話:crossDomain: true,xhrFields: {withCredentials: true}
六:安全隐患
如果程式猿偷懶将Access-Control-Allow-Origin設定為:Access-Control-Allow-Origin: * 允許任何來自任意域的跨域請求,那麼久存在被 DDoS攻擊的可能。
and待補充。。。
七、如有不足,歡迎指出并補充。
轉載請注明出處,謝謝。