標籤:logs 服務 父頁面 不同 代碼 class 請求 pos 資料封裝
(一):動態指令碼注入的方法.即在頁面中動態產生<script>指令碼標籤,另其src指向其它域的js檔案(即是src屬性為不同域的URL). (一般用於不同域之間的跨域)
var scriptElement = document.createElement(‘script‘);
scriptElement.src = ‘URL‘;
document.getElementsByTagName(‘head‘)[0].appendChild(scriptElement);
通過動態建立script標籤就可以載入其它域的js檔案,然後通過本頁面就可以調用載入後js檔案的函數,這樣做的缺陷就是不能載入其它域的文檔
script標籤的 src屬性不一定必須是一個存在的js檔案,也可以是一個http handler的url,只要這個http handler返回的是一個text/JavaScript類型的響應就可以了
例:
<script type="text/javascript"> var script = document.createElement("script"); function ajaxCross(){ script.type = "text/javascript"; script.src = "http://xipang.hfutonline.net/public/test"; } window.onload = function(){ ajaxCross(); document.getElementsByTagName("head")[0].appendChild(script); } function getAnswer(){ console.log(date); } script.onload = function() { getAnswer(); }</script>
通過請求伺服器端返回的資料是var date = {}的形式;
缺點:
不能佈建要求頭資訊;
參數傳遞也只能使用GET方式;
不能佈建要求的逾時處理或重試,就算失敗了也不一定知道;
必須等資料都已經返回才能訪問他們,而且不能訪問要求標頭資訊,也不能把整個響應訊息當作字串來處理;
還有一點就是響應訊息作為指令碼標籤的源碼,必須是可執行檔javascript代碼,不能使用其它任何格式的資料
function jsonCallback(jsonString){ //jsonCallback進行資料封裝
var data = eval(‘(‘ +jsonString +‘)‘)
//資料處理
}
優點:因為響應訊息作為js執行,所以速度非常快
用伺服器端的XmlHttpRequest代理實現跨域訪問
我們不能在瀏覽器端直接使用AJAX來跨域訪問資源,但是在伺服器端是沒有這種跨域安全限制的。所以,我們只需要讓伺服器端幫我們完成“跨域訪問”的工作,然後在瀏覽器端用AJAX擷取伺服器端“跨域訪問”的結果就可以了。這就是所謂的在伺服器端建立一個XmlHttpRequest代理,通過這個代理來訪問其他網域名稱下的資源。將後台作為代理,每次對其它域的請求轉交給本域的後台,本域的後台通過類比http請求去訪問其它域,再將返回的結果返回給前台,這樣做的好處是,無論訪問的是文檔,還是js檔案都可以實現跨域。
頁面上javascript指令碼:
<script type="text/javascript"><!-- Var sUrl="http://Jipiao.taobao.com/proxy.do"; //本域下Proxy 位址 var callback = { success: function(res) { alert(res.responseText); }, failure: function(res) { alert(‘failure‘);}, argument:{} } YAHOO.util.Connect.asyncRequest(‘GET‘, sUrl, callback, null); // --></script>
完成域A服務端的Proxy程式(這裡假定是一個servlet),偽碼如下:
Public class Proxy extends …….{ ..doGet(……..){ HttpClient client=……; GetMethod get=new GetMethod("www.baidu.com/xxxxx.do");//訪問域B的連結 int statusCode = client.executeMethod(get); if (statusCode != HttpStatus.SC_OK) { byte[] responseBody = get.getResponseBody(); String res=new String(responseBody); Httpresponse.getWriter().write(res);//將資料返回給域A } } }
基於iframe實現跨域(一般用於父域子域之間的跨域)
基於iframe實現的跨域要求兩個域具有aa.xx.com,bb.xx.com這種特點,也就是兩個頁面必須屬於一個基礎域(例如都是xxx.com,或是xxx.com.cn),使用同一協議(例如都是 http)和同一連接埠(例如都是80),這樣在兩個頁面中同時添加document.domain,就可以實現父頁面調用子頁面的函數
頁面一:
<html> <head> <script> document.domain = "xx.com"; function aa(){ alert("p"); } </script> </head> <body> <iframe src="http://localhost:8080/CmsUI/2.html" id="i"> </iframe> <script> document.getElementById(‘i‘).onload = function(){ var d = document.getElementById(‘i‘).contentWindow; d.a(); }; </script> </body> </html>
頁面二:
<html> <head> <script> document.domain = "xx.com"; function a(){ alert("c"); } </script> </head> <body> </body> </html>
也可以用iframe實現不同域之間的跨域,不過比較麻煩
當兩個域不同時,如果想相互調用,那麼同樣需要兩個域都是由你來開發才可以。用iframe可以實現資料的互相調用。解決方案就是用window.location對象的hash屬性。hash屬性就是http://domian/web/a.htm#dshakjdhsjka 裡面的#dshakjdhsjka。利用JS改變hash值網頁不會重新整理,可以這樣實現通過JS訪問hash值來做到通訊。不過除了IE之外其他大部分瀏覽器只要改變hash就會記錄曆史,你在前進和後退時就需要處理,非常麻煩。不過再做簡單的處理時還是可以用的。大體的過程是頁面a和頁面b在不同域下,b通過iframe添加到a裡,a通過JS修改iframe的hash值,b裡面做一個監聽(因為JS只能修改hash,資料是否改變只能由b自己來判斷),檢測到b的hash值被修改了,得到修改的值,經過處理返回a需要的值,再來修改a的hash值(這個地方要注意,如果a 本身是那種查詢頁面的話比如http://domian/web/a.aspx?id=3,在b中直接parent.window.location是無法取得資料的,同樣報沒有許可權的錯誤,需要a把這個傳過來,所以也比較麻煩),同樣a裡面也要做監聽,如果hash變化的話就取得返回的資料,再做相應的處理。
(二):“Firefox 3”中跨域XHR,是基於W3C跨網站請求。通過設定Access-Control-Allow-Origin頭部(自訂的HTTP頭部),遠端資源有權決定自身是否可以被遠程瀏覽器訪問.實現方法如下
Access-Control-Allow-Origin:http://www.wrox.com即通過指定哪個域可以訪問該資源來實現,此頭部資訊就指定了只有www.wrox.com域才有存取權限
Access-Control-Allow-Origin:*表明可以允許所有請求訪問當前資源
Origin頭部包含請求頁面的頭部(協議,網域名稱,連接埠),如果伺服器確定請求被通過,會發送一個 Access-Control-Allow-Origin頭部作為響應發送請求的同一個源,若為一個公用資源則返回 Access-Control-Allow-Origin:*
請求另一個域的資源:使用標準的XHR對象,並為open()方法傳入一個絕對URL
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = funtion(){
if(xhr.readyState == 4){
......
}
};
xhr.open(‘get‘,‘http://somewhere -else.com/page‘,true);
xhr.send(null);
缺點:
不能使用setRequestHeader()設定自訂頭部
不會發送也不會接收cookie
getAllResponseHeaders()方法只能返回Null 字元串
優點:跨域的XHR對象允許訪問statues和statusText屬性
(三):IE8中的XDomainRequest對象實現跨域
XDR對象使用方法與XHR的類似,首先建立一個XDomainRequest的執行個體,調用open(),再調用send(),但open()只接受兩個參數,即請求的類型和URL,請求返回之後會觸發load事件,響應的資料會儲存在responseText中,響應失敗就會觸發error事件,可以調用abort()來終止請求,例:
var xdr = new XDomainRequest();
xdr.onload = function(){alert(xdr.responseText);
xdr.onerror = function(){alert("an error occured.")}
xdr.timeout = 1000; //1秒過後會觸發timeout事件
xdr.ontimeout = function(){alert("request took too long")}
xdr.open("get","http://www.somewhere-else.com/page/");
xdr.send(null);
註:
被請求的資源可以根據它認為合適的任意資料(使用者代理程式,來源頁面)來決定是否設定Access-Control-Allow-Origin頭部
cookie不會隨請求發送,也不會隨響應返回
只能佈建要求頭部資訊中的Content-Type欄位
不能訪問回應標頭部資訊
只支援GET和POST請求
只能訪問Access-Control-Allow-Origin頭部欄位設定為*的資源
所有請求都是非同步,不能建立同步請求
接受響應之後,只能訪問響應的原始文本,沒辦法確定響應的狀態代碼
ajax跨域問題