各瀏覽器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個字節
方法一、document.domain+iframe的設置
對於主域相同而子域不同的例子,可以通過設置document.domain的辦法來解決。具體的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html兩個文件中分別加上document.domain = ‘a.com’;然後通過a.html文件中創建一個iframe,去控制iframe的contentDocument,這樣兩個js文件之間就可以“交互”了。當然這種辦法只能解決主域相同而二級域名不同的情況,如果你異想天開的把script.a.com的domian設爲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>
方法二、Jquery的Ajax的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(包括操作cookie、Dom等等)。根據這一點,可以方便地通過創建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=[}
方法四、利用iframe和location.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!'; // 這裏是要傳輸的數據,大小一般爲2M,IE和firefox下可以大至32M左右
// 數據格式可以自定義,如json、字符串
</script>
在應用頁面(a.com/app.html)中監聽iframe的onload事件,在此事件中設置這個iframe的src指向本地域的代理文件(代理文件和應用頁面在同一域下,所以可以相互通信)。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>
總結起來即:iframe的src屬性由外域轉向本地域,跨域數據即由iframe的window.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的寬高了。
在愛卡評論系統中就涉及到了這個問題,用的就是這個方法。
方法七 、 原始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對象裏找到它。