因爲同源策略限制,默認狀況下,使用XHR對象只能訪問與包含它的頁面位於同一個域(相同的協議、域名和端口)中的資源。要實現合理的跨域資源請求,有兩種策略:1.跨域資源共享 ,2.利用DOM中可以執行跨域請求的功能。本文詳述了第一種策略的實現方法。php
跨域資源共享(CORS)背後的基本思想,就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或相應是應該成功,仍是應該失敗。這種方法須要修改服務器代碼。json
若是隻是簡單的使用GET或POST發送請求,而且沒有自定義的頭部,且主體內容是text/plain。在發送該請求時,需附加一個額外的origin頭部,其中包含請求頁面的源信息(協議、域名和端口),服務器會根據這個頭部信息來決定是否給與響應。頭部實例以下:跨域
origin:http://www.snsartme.com
大部分瀏覽器都經過XMLHttpRequest對象實現了CORS的原生支持。在訪問不一樣域的資源時,無需額外編寫代碼就會自動發送origin頭部。只須要在open()方法中傳入絕對URL便可,例如:瀏覽器
1 var xhr=new XMLHttpRequest(); 2 xhr.onreadystatechange=function(){ 3 if(xhr.readyState==4){ 4 if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ 5 alert("成功"+xhr.responseText); 6 }else{ 7 alert("失敗"+xhr.responseText); 8 } 9 } 10 }; 11 12 xhr.open("get","http://www.somewhere.com/test.php",true); 13 xhr.send(null);
若是服務器認爲這個請求能夠接受,就會在Access-Control-Allow-origin頭部中回發相同的源信息(若是是公共資源,能夠回發 ‘ * ’),好比在服務器的php代碼中加入如下代碼,來發送Access-Control-Allow-origin頭部:緩存
header('Access-Control-Allow-origin:http:/www.snsartme.com');
簡單請求有以下一些限制:服務器
1. 不能使用setRequestHeader()方法設置自定義頭部。cookie
2. 不能發送和接受cookie。post
3. 調用getALLResponseHeaders()方法總會返回空字符串。jsonp
預檢請求(Preflighted Requests)必須首先使用OPTIONS方法發起一個預檢請求到服務器,以獲知服務器是否容許該實際請求。「預檢請求」的使用,能夠避免跨域請求對服務器的用戶數據產生沒法預知的影響。OPTIONS方法發出的請求頭部以下:spa
Origin:與簡單的請求相同。
Access-Control-Request-Method:請求使用的方法
Access-Control-Request-Headers:自定義的頭部信息,多個頭部以逗號分隔。
當使用setRequestHeader()方法設置了自定義頭部,或者請求方法不是get或post時,就會自動發送預檢請求:
1 var xhr=new XMLHttpRequest(); 2 xhr.open("get","http://www.somewhere.com/test.php",true); 3 xhr.setRequestHeader("x-token", "I am x-token"); 4 xhr.send(null);
服務器經過在響應中發送以下頭部信息與瀏覽器溝通,php代碼以下:
1 header('Access-Control-Allow-origin:http://www.snsartme.com'); 2 header('Access-Control-Allow-Methods: GET,POST');//容許的方法 3 header('Access-Control-Allow-Headers:x-token'); //容許的頭部 4 header('Access-Control-Max-Age:7800'); //應該將預檢請求緩存多長時間
默認狀況下,跨域請求不提供憑據(cookie,HTTP認證及客戶端SSL證實等)。經過將xhr的withCredentials屬性設置爲true,能夠指定某個請求應該發送憑據。若是服務器接送帶憑據的請求,會用下面的HTTP頭部來響應。
header('Access-Control-Allow-Credentials: true');
下一篇會詳解利用DOM中可以執行跨域請求的功能實現跨域資源訪問,主要是jsonp技術