Ajax跨域請求

各瀏覽器HTTP Get請求URL最大長度並不相同,幾類常用瀏覽器最大長度及超過最大長度後提交情況如下:

IE6.0                :url最大長度2083個字符,超過最大長度後無法提交。
IE7.0                :url最大長度2083個字符,超過最大長度後仍然能提交,但是隻能傳過去2083個字符。
firefox 3.0.3     :url最大長度7764個字符,超過最大長度後無法提交。
Opera 9.52       :url最大長度7648個字符,超過最大長度後無法提交。
Google Chrome 2.0.168   :url最大長度7713個字符,超過最大長度後無法提交。

 

微軟的權威解釋,IE的url最大長度是2083個字節,可以用於GET傳遞數據的長度是2048個字節

spacer.gifwKiom1SGnArhxHoZAAXD8Ec-GPk197.jpg

方法一document.domain+iframe的設置
對於主域相同而子域不同的例子,可以通過設置document.domain的辦法來解決。具體的做法是可以在http://www.a.com/a.htmlhttp://script.a.com/b.html兩個文件中分別加上document.domain = ‘a.com’;然後通過a.html文件中創建一個iframe,去控制iframecontentDocument,這樣兩個js文件之間就可以“交互”了。當然這種辦法只能解決主域相同而二級域名不同的情況,如果你異想天開的把script.a.comdomian設爲alibaba.com那顯然是會報錯地!代碼如下:
www.a.com上的a.html

document.domain = ‘a.com’;
var ifr = document.createElement(‘iframe’);
ifr.src = ‘http://script.a.com/b.html‘;
ifr.style.display = ‘none’;
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在這裏操縱b.html
     alert(doc.getElementsByTagName(“h1″)[0].childNodes[0].nodeValue);
};
script.a.com上的b.html
document.domain = ‘a.com’;

這種方式適用於{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何頁面相互通信。
備註:某一頁面的domain默認等於window.location.hostname。主域名是不帶www的域名,例如a.com,主域名前面帶前綴的通常都爲二級域名或多級域名,例如www.a.com其實是二級域名。 domain只能設置爲主域名,不可以在b.a.com中將domain設置爲c.a.com
問題:
1、安全性,當一個站點(b.a.com)被***後,另一個站點(c.a.com)會引起安全漏洞。
2、如果一個頁面中引入多個iframe,要想能夠操作所有iframe,必須都得設置相同domain

源文檔 <http://www.cnblogs.com/zxktxj/archive/2012/02/23/2365019.html>

方法二、JqueryAjax的JSonP 

getDataByJsonp:function(u,p,f){try{ $.ajax({ type:”get”,url:u,data:p,dataType:”jsonp”,success:function(msg){ f(msg);}});}catch(e){}}//var _url=”http://my2.xcar.com.cn/interface/ajax_friend_jk_cms.php”;var _param=”action=”+act+”&fuid=”+uid+”?callback=?”;
XcarApp.Tools.getDataByJsonp(_url,_param,function(msg){Console.log(msg);})
 
function Jsonp(o){
    var rand = “Jsonp”+parseInt(Math.random()*10000);
    var _url = o.url+”&callback=”+rand;
    var script = document.createElement(“script”);
    script.id = rand;
    script.src = _url;
    window[rand]= function(e){
        o.callback(e);
        window[rand] = null;
        script.parentNode.removeChild(script);
    }
    document.getElmentsByTagName(‘head’)[0].appendChild(script);
}

 
 
服務器端需要做的操作:

$data=array(‘msgData’=>’Success’,’errno’=>0);
Echo
  
$_GET["callback"].”(“.json_encode($data).”)”;

 
方法三、用<script>標籤動態地加載,程序端動態輸出JS變量。
原理:雖然瀏覽器默認禁止了跨域訪問,但並不禁止在頁面中引用其他域的JS文件,並可以自由執行引入的JS文件中的function(包括操作cookieDom等等)。根據這一點,可以方便地通過創建script節點的方法來實現完全跨域的通信。

 

1))客戶端動態創建<script>標籤,且設置請求地址爲務器端地址,大概如下:

    

    <script id=”callbackJS” src=”http://test.xcar.comm.cn/1.php”><script>


 

2) 在服務器接收端,會動態地輸出JS 代碼,如下:

<?php
    echo “var a={u:2323,name:’xxxx’}”;
?>


 

3)客戶端監測<script>標籤的加載狀態,會將服務端輸出的結果顯示在script標籤之間,我們再利用加載完成後回調函數進行下一步處理

   

   
<script id=”callbackJS” src=”http://test.xcar.comm.cn/1.php”>
 
var a={u:2323,name:’xxxx’}
 
<script>



[code]

 

function loadScript(url,callback){
var script = document.createElement('script');
script.type= "text/javascript";
if(script.readyState){// IE
script.onreadystatechange = function(){
if(script.readyState == 'loaded' || script.readyState == 'complete'){
script.onreadystatechange = null;
callback();
}
}
}else{ // !IE
script.onload = function(){
callback();
}
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}


 

[/code]
 
DEMO:
loadScript(_url, XcarApp.Member.login_reponse,’login_request’);
【注意】 服務器端返回的數據類型必須爲 JS類型
Var login_result=[}


方法四、利用iframelocation.hash

這個辦法比較繞,但是可以解決完全跨域情況下的腳步置換問題。原理是利用location.hash來進行傳值。在url http://a.com#helloword 中的‘#helloworld’就是location.hash,改變hash並不會導致頁面刷新,所以可以利用hash值來進行數據傳遞,當然數據容量 是有限的。假設域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html傳遞信息,cs1.html首先創建自動創建 一個隱藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html頁面,這時的hash值可以做參數傳遞用。 cs2.html響應請求後再將通過修改cs1.html的hash值來傳遞數據(由於兩個頁面不在同一個域下IE、Chrome不允許修改 parent.location.hash的值,所以要藉助於a.com域名下的一個代理iframe;Firefox可以修改)。同時在 cs1.html上加一個定時器,隔一段時間來判斷location.hash的值有沒有變化,一點有變化則獲取獲取hash值。代碼如下
先是a.com下的文件cs1.html文件:

function startRequest(){
    
var ifr = document.createElement('iframe');
    
ifr.style.display = 'none';
    
ifr.src = '
http://www.cnblogs.com/lab/cscript/cs2.html#paramdo
';
     
document.body.appendChild(ifr);
}
function checkHash() {
    
try {
        
var data = location.hash ? location.hash.substring(1) : '';
        
if (console.log) {
            
console.log('Now the data is '+data);
        
}
    
} catch(e) {};
}
setInterval(checkHash, 2000);
cnblogs.com
域名下的
cs2.html:
//
模擬一個簡單的參數處理操作
switch(location.hash){
    
case '#paramdo':
        
callBack();
        
break;
    
case '#paramset':
        
//do something……
        
break;
}
function callBack(){
    
try {
        
parent.location.hash = 'somedata';
    
} catch (e) {
        // ie
、
chrome
的安全機制無法修改
parent.location.hash
,
        // 
所以要利用一箇中間的
cnblogs
域下的代理
iframe
        
var ifrproxy = document.createElement('iframe');
        
ifrproxy.style.display = 'none';
        ifrproxy.src = '
http://a.com/test/cscript/cs3.html#somedata
';    // 
注意該文件在
"a.com"
域下
         
document.body.appendChild(ifrproxy);
    
}
}

a.com下的域名cs3.html
//因爲parent.parent和自身屬於同一個域,所以可以改變其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);
當然這樣做也存在很多缺點,諸如數據直接暴露在了url中,數據容量和類型都有限等……
 
方法五、window.name實現的跨域數據傳輸
這篇文章是對 JavaScript跨域總結與解決辦法 的補充
有三個頁面:
a.com/app.html:應用頁面。
a.com/proxy.html:代理文件,一般是一個沒有任何內容的html文件,需要和應用頁面在同一域下。
b.com/data.html:應用頁面需要獲取數據的頁面,可稱爲數據頁面。

實現起來基本步驟如下:
在應用頁面(a.com/app.html)中創建一個iframe,把其src指向數據頁面(b.com/data.html)。
數據頁面會把數據附加到這個iframe的window.name上,data.html代碼如下:
<script type="text/javascript">
window.name = 'I was there!';    // 
這裏是要傳輸的數據,大小一般爲2MIEfirefox下可以大至32M左右
// 
數據格式可以自定義,如json、字符串
</script>

在應用頁面(a.com/app.html)中監聽iframeonload事件,在此事件中設置這個iframesrc指向本地域的代理文件(代理文件和應用頁面在同一域下,所以可以相互通信)。app.html部分代碼如下:

<script type="text/javascript">
var state = 0,
iframe = document.createElement('iframe'),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name;    // 
讀取數據
alert(data);    //
彈出
'I was there!'
} else if (state === 0) {
state = 1;
iframe.contentWindow.location = "
http://a.com/proxy.html
";    // 
設置的代理文件
}
};
iframe.src = '
http://b.com/data.html
';
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload  = loadfn;
}
document.body.appendChild(iframe);
</script>

獲取數據以後銷燬這個iframe,釋放內存;這也保證了安全(不被其他域frame js訪問)。

<script type="text/javascript">
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
</script>

總結起來即:iframesrc屬性由外域轉向本地域,跨域數據即由iframewindow.name從外域傳遞到本地域。這個就巧妙地繞過了瀏覽器的跨域訪問限制,但同時它又是安全操作。 

 

方法六 、 代理方法proxy.html

 

【原理】:假設兩個域名 info.xcar.com.cn  newxcar.com.cn

。在要進行跨域的兩個域名的根目錄下都放一個proxy.html的文件。即 info.xcar.com.cn/proxy.html; newxcar.com.cn/proxy.html

。在info.xcar.com.cn下的一個頁面中創建一個iframe 並且指向 newxcar.com.cn下的一個頁面。

。在iframe引用的面面中(newxcar.com.cn),動態創建一個html script標籤,讓這個標籤的SRC指向info.xcar.com.cn域名的 proxy.html文件(還可以傳遞參數)

。這位就可以在proxy.html中來操作info.xcar.com.cn下面iframe的寬高了。

 

在愛卡評論系統中就涉及到了這個問題,用的就是這個方法。

 

計算機生成了可選文字: proxY.html+<br />婦婦婦婦婦婦利<br />.n沁.‘腸l'.com.cn頁面下十<br /><l介ame>src指向newcar.而而而萬刃茵<br />prox丫htm!十 

方法七 、 原始script標籤 利用JSONP協議,等同方法2 jQuery的實現

JSONP是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。JSON系統開發方法是一種典型的面向數據結構的分析和設計方法,以活動爲中心,一連串的活動的順序組合成一個完整的工作進程。

之所以會有跨域這個問題的產生根本原因是瀏覽器的同源策略限制,理解同源策略的限制同源策略是指阻止代碼獲得或 者更改從另一個域名下獲得的文件或者信息。也就是說我們的請求地址必須和當前網站的地指相同。同源策略通過隔離來實現對資源的保護。這個策略的歷史非常悠 久從Netscape Navigator 2.0時代就開始了。

解決這個限制的一個相對簡單的辦法就是在服務器端發送請求,服務器充當一個到達第三方資源的代理中繼。雖然是用廣泛但是這個方法卻不夠靈活。

實現原理:

 

1))客戶端動態創建<script>標籤,且設置請求地址爲務器端地址,大概如下:

        <script id="callbackJS" src="http://test.xcar.comm.cn/1.php&callback=Calbackxxxxx3234234234"><script>

 

2) 在服務器接收端,會動態地輸出JS 代碼,如下:

<?php
 $callback=$_GET["callback"];
    echo   $callback.”({errno:4001,msg:’xxxx’})”;
?>


 

3)客戶端監測<script>標籤的加載狀態,會將服務端輸出的結果顯示在script標籤之間,我們再利用加載完成後回調函數進行下一步處理

 

 

function jsonpCallback(data){
alert(data.uname);
}
<script src=”http://www.comment.com/test.php?jsonp=jsonpCallback”></script>


 

 


 

其實就是在函數裏定義了CallBack函數,返回成功後,直接能在window對象裏找到它。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章