CORS
全稱:Cross-Origin Resource Sharing
中文意思:跨域資源共享?
好吧,目前中文方面的資料還比較少,能搜索到的那僅有的幾篇相關介紹,也幾乎是雷同的。
最近工作上也有用到CORS的地方,隨便做點分享吧,也當是筆記。
大家也知道,XMLHttpRequest接口是Ajax的根本,而Ajax考慮到安全性的問題,是禁止跨域訪問資源的。
也就是說:www.a.com的頁面無法通過Ajax來調用www.b.com的資源。
很多人又會說,但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.b.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來寫,還是有些地方需要注意的。
1、不要設置X-Requested-With頭
因為跨域訪問,如需帶header,服務器端必須要allow,不然報錯。
setRequestHeader("X-Requested-With", "XMLHttpRequest")主要用在Ajax調用資源時,服務器能判斷該次請求是Ajax的。
2、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)
本文鏈接:http://www.cnblogs.com/maplejan/archive/2012/12/02/2797864.html