CORS(Cross-Origin Resource Sharing) 跨域資源共享javascript
CORSphp
全稱:Cross-Origin Resource Sharinghtml
中文意思:跨域資源共享?前端
好吧,目前中文方面的資料還比較少,能搜索到的那僅有的幾篇相關介紹,也幾乎是雷同的。html5
最近工做上也有用到CORS的地方,隨便作點分享吧,也當是筆記。java
你們也知道,XMLHttpRequest接口是Ajax的根本,而Ajax考慮到安全性的問題,是禁止跨域訪問資源的。ajax
也就是說:www.a.com的頁面沒法經過Ajax來調用www.b.com的資源。json
不少人又會說,但jQuery的$.ajax()明明就能夠跨域訪問啊!跨域
對,的確是跨了,但那是jsonp!關於jsonp的介紹也不少了,這裏不扯。瀏覽器
其實jQuery的$.ajax()方法中,也能夠實現CORS,只要服務器端配合,跨域就不須要使用jsonp。
CORS是XMLHttpRequest Level 2中新增長的功能
支持狀況以下
支持狀況還算良好(假如無視IE的話)。
移動端的開發,除了Opera Mini還不支持,其餘設備的版本支持狀況也很好。
好了,下面進入實戰,直接說說使用方法。
1 var xhr = new XMLHttpRequest(); 2 xhr.open("POST", "http:// www.2cto.com ", true); 3 xhr.send();沒有看錯!就是這麼簡單!
和Ajax的調用方法是毫無差別的,須要的只是服務器端的配合。
服務器端如何配置?
PHP:只須要使用以下的代碼設置便可。
1 <?php 2 header("Access-Control-Allow-Origin:*"); 以上的配置的含義是容許任何域發起的請求均可以獲取當前服務器的數據。
固然,這樣有很大的危險性,惡意站點可能經過XSS攻擊咱們的服務器。
若是僅支持www.a.com這個站跨域訪問,那就:
1 <?php 2 header("Access-Control-Allow-Origin: http://www.a.com"); 這樣就基本配置ok了~
前端的部分,若是須要跨域向服務器發cookies
還須要設置一個屬性:withCredentials
1 var xhr = new XMLHttpRequest(); 2 xhr.open("POST", "http://www.b.com", true); 3 xhr.withCredentials = true; //支持跨域發送cookies 4 xhr.send(); 固然,服務器端也要設置
1 <?php 2 header("Access-Control-Allow-Credentials: true");
好吧,下面說說須要注意的地方。
若是不使用第三方庫,用原生javascript來寫,仍是有些地方須要注意的。
一、不要設置X-Requested-With頭
由於跨域訪問,如需帶header,服務器端必需要allow,否則報錯。
setRequestHeader("X-Requested-With", "XMLHttpRequest")主要用在Ajax調用資源時,服務器能判斷該次請求是Ajax的。
二、INVALID_STATE_ERR: DOM Exception 11
這是一個神奇的錯誤,網上找了一下,也沒什麼較爲明確的答覆。但我卻在手機端遇到了這個問題!
測試了一下:在IOS4和IOS5的UC瀏覽器、Safari、Chrome,進行CORS訪問均會報這個錯,
Android4.0原生瀏覽器,也沒法正常CORS(沒有測試2.3和2.2)
估計也是報這個錯,但沒控制檯,因此沒法查bug。
Android4.0下的Chrome和UC均可以順利CORS。
本覺得是瀏覽器兼容的問題,通過蛋疼的排查以後,發現...
咱們能夠看一下,下面兩段代碼有啥差別?
1 var xhr = new XMLHttpRequest(); 2 xhr.withCredentials = true; //支持跨域發送cookies 3 xhr.open("POST", "http://weibo.com/demo/b/index.php", true); 4 xhr.send();1 var xhr = new XMLHttpRequest(); 2 xhr.open("POST", "http://weibo.com/demo/b/index.php", true); 3 xhr.withCredentials = true; //支持跨域發送cookies 4 xhr.send();惟一的差別就是xhr.withCredentials = true; 的位置。
但就是這個差異,致使第一段代碼沒法順利在手機端運行,並報INVALID_STATE_ERR: DOM Exception 11這個錯!
而在桌面版瀏覽器下,兩段代碼均可以順利運行!
因此,之後設置withCredentials屬性時,必定要在open方法以後!
篇幅有限,想要參考更多的CORS,能夠查看下面的參考網站.
參考:
http://www.html5rocks.com/en/tutorials/cors/
https://developer.mozilla.org/en-US/docs/HTTP_access_control (MDN十分詳細的講解)
http://enable-cors.org/index.html (不一樣的服務器怎麼配置CORS)
http://people.opera.com/tiffanyb/2011/cors/ (來自Opera的CORS測試Demo)
http://arunranga.com/examples/access-control/ (另外一個CORS的測試Demo)