前言
通過XHR實現ajax通信的一個主要限制是 跨域安全策略。XHR對象只能訪問與包含他的頁面位於同一個域的資源。當發起一個資源請求的時候,請求頭會帶有一個 Origin頭部,響應頭會帶有一個Access-Origin-Allow-Origin,如下:
Origin:http://www.test.com
Access--Control-Allow-Origin: http://www.test.com // Access--Control-Allow-Origin: * // 代表公共資源
如果這個頭部和Origin頭部不相符合的時候,瀏覽器會駁回請求。於是就出現了跨域請求技術,下面是幾種方式的總結.
實現一:跨瀏覽器的CORS
1 function createCORSRequest(method,url) { 2 var xhr = new XMLHttpRequest(); 3 if ("withCredentials" in xhr){ 4 xhr.open(method,url,true); 5 }else if(typeof XDomainRequest!== "undifined"){ 6 xhr=new XDomainRequest(); 7 xhr.open(method,url); 8 }else{ 9 xhr=null; 10 } 11 return xhr; 12 } 13 14 var request=createCORSRequest('get','http://www.test.com'); 15 if(request){ 16 request.onload=function(){ 17 // onreadystatechange檢測成功 18 // 處理 requset.responseText 19 } 20 request.onerror=function(){ 21 // 處理請求失敗 22 } 23 requset.send(null); 24 }
上面是跨瀏覽器的實現方式,下面分析一下:
IE對CORS的實現
IE8中引入了XDR(XDomainRequest)類型,此類型和XMLHttpResquest相似,但是可以實現安全的跨域通信。
不同之處:
① 不能通過setRequestHeader()設置自定義頭部,只能設置請求頭部信息的Content-Type字段, xhr.contentType
② 不能訪問響應頭信息,即調用getAllResponseHeaders()總是返回空字符串
③ 不能發送和接受cookie
XDR對象的方法
① open() 只接受兩個參數,所有XDR請求都是異步的
② send() 同XHR對象一樣
其他事件
1 var xdr=new XDomainRequest(); 2 xdr.onload=function(){ 3 // xdr.responseText 響應的原始文本 4 // 無法確定 響應的狀態代碼,即無 xhr.readyState和xhr.status 5 } 6 xdr.onerror=function(){ 7 alert("An error occurred."); 8 } 9 xdr.open('get',"url"); 10 xdr.send(null);
其他瀏覽器對CORS的實現
FireFox3.5+,Safari4+,Chrome等等都實現了原生CORS的支持。但是默認情況下,跨域請求不提供憑據,可以設置withCredentials表示帶憑據的請求
於是,設置跨瀏覽器的CORS的時候,可以先檢測是否帶 withCredentials 屬性,若無,再檢測是否存在XDomainRequest對象。
實現二: 圖像Ping
可行性:網頁可以從任何網頁中加載圖像,不用擔心跨域問題。
具體實現:利用 img 標簽,動態創建圖像。
1 var img=new Image(); 2 img.onload=img.onerror=function(){ 3 alert("done"); 4 } 5 img.src="http://www.example.com/test?name=Kasmine";
這里創建了一個Image實例,通過 img.src 向服務器發起GET請求(參數為name),服務器收到請求后,通過對請求url的解析,判斷請求內容。
應用:圖像Ping主要用於用戶點擊頁面或者瀏覽量的統計。
缺點:只有get請求,不能訪問服務器的響應文本
實現三: JSONP
jsonp :“JSON with padding”顧名思義就是 包含在函數回調的json數據。具體實例如下:
1 function handleResponse(response) { 2 // 處理 response 3 } 4 var script=document.createElement("script"); 5 script.src='http://www.example.com?callback=handleResponse'; 6 document.body.insertBefore(script,document.body.firstChild);
<script>標簽和<img>標簽一樣,不受訪問域的限制。首先我們創建一個 script 元素,插入到頁面后立刻執行。客戶端定義了一個名為handleResponse的回調函數,向 http://www.example.com 發起GET請求,服務器端進行響應:
callback({"name":"Nicholes"});
客戶端在響應到來時,會調用 回調函數 handleResponse
實現四:修改document.domain跨子域
兩個域名必須屬於同一個基礎域名
實現五:通過使用HTML5的window.postMessage方法來傳送數據
【始終使用origin和source屬性驗證發件人的身份】
1 窗口A: 2 window.postMessage(msg,urlOfB); 3 窗口B: 4 window.onmessage(event){ 5 var data=event.data; 6 var origin=event.origin; 7 }
小結
同源策略是XHR的一個約束,他要求“相同的域,相同的端口,相同的協議”才能進行通信。於是就出現了跨域訪問的技術。
實現 跨域還有其他的方法,在這里就不多說了,日后學習到了,再繼續補上~