JavaScript出于安全方面的考慮,不允許跨域調(diào)用其他頁面的對象。但在安全限制的同時也給注入iframe或是ajax應(yīng)用上帶來了不少麻煩。這里把涉及到跨域的一些問題簡單地整理一下:

成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供太湖網(wǎng)站建設(shè)、太湖做網(wǎng)站、太湖網(wǎng)站設(shè)計、太湖網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、太湖企業(yè)網(wǎng)站模板建站服務(wù),10余年太湖做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
首先什么是跨域,簡單地理解就是因為JavaScript同源策略的限制,a.com 域名下的js無法操作b.com或是c.a.com域名下的對象。
特別注意兩點(diǎn):
第一,如果是協(xié)議和端口造成的跨域問題“前臺”是無能為力的,
第二:在跨域問題上,域僅僅是通過“URL的首部”來識別而不會去嘗試判斷相同的ip地址對應(yīng)著兩個域或兩個域是否在同一個ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解為“Domains, protocols and ports must match”。
接下來簡單地總結(jié)一下在“前臺”一般處理跨域的辦法,后臺proxy這種方案牽涉到后臺配置,這里就不闡述了,有興趣的可以看看yahoo的這篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls》
1、document.domain+iframe的設(shè)置
對于主域相同而子域不同的例子,可以通過設(shè)置document.domain的辦法來解決。具體的做法是可以在和兩個文件中分別加上document.domain = ‘a(chǎn).com’;然后通過a.html文件中創(chuàng)建一個iframe,去控制iframe的contentDocument,這樣兩個js文件之間就可以“交互”了。當(dāng)然這種辦法只能解決主域相同而二級域名不同的情況,如果你異想天開的把script.a.com的domian設(shè)為alibaba.com那顯然是會報錯地!代碼如下:
上的a.html
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = '';
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';
這種方式適用于{, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何頁面相互通信。
備注:某一頁面的domain默認(rèn)等于window.location.hostname。主域名是不帶www的域名,例如a.com,主域名前面帶前綴的通常都為二級域名或多級域名,例如其實是二級域名。 domain只能設(shè)置為主域名,不可以在b.a.com中將domain設(shè)置為c.a.com。
問題:
1、安全性,當(dāng)一個站點(diǎn)(b.a.com)被攻擊后,另一個站點(diǎn)(c.a.com)會引起安全漏洞。
2、如果一個頁面中引入多個iframe,要想能夠操作所有iframe,必須都得設(shè)置相同domain。
2、動態(tài)創(chuàng)建script
雖然瀏覽器默認(rèn)禁止了跨域訪問,但并不禁止在頁面中引用其他域的JS文件,并可以自由執(zhí)行引入的JS文件中的function(包括操作cookie、Dom等等)。根據(jù)這一點(diǎn),可以方便地通過創(chuàng)建script節(jié)點(diǎn)的方法來實現(xiàn)完全跨域的通信。具體的做法可以參考YUI的Get Utility
這里判斷script節(jié)點(diǎn)加載完畢還是蠻有意思的:ie只能通過script的readystatechange屬性,其它瀏覽器是script的load事件。以下是部分判斷script加載完畢的方法。
js.onload = js.onreadystatechange = function() {
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
?// callback在此處執(zhí)行
?js.onload = js.onreadystatechange = null;
}
};
3、利用iframe和location.hash
這個辦法比較繞,但是可以解決完全跨域情況下的腳步置換問題。原理是利用location.hash來進(jìn)行傳值。在url: 中的‘#helloworld’就是location.hash,改變hash并不會導(dǎo)致頁面刷新,所以可以利用hash值來進(jìn)行數(shù)據(jù)傳遞,當(dāng)然數(shù)據(jù)容量是有限的。假設(shè)域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html傳遞信息,cs1.html首先創(chuàng)建自動創(chuàng)建一個隱藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html頁面,這時的hash值可以做參數(shù)傳遞用。cs2.html響應(yīng)請求后再將通過修改cs1.html的hash值來傳遞數(shù)據(jù)(由于兩個頁面不在同一個域下IE、Chrome不允許修改parent.location.hash的值,所以要借助于a.com域名下的一個代理iframe;Firefox可以修改)。同時在cs1.html上加一個定時器,隔一段時間來判斷l(xiāng)ocation.hash的值有沒有變化,一點(diǎn)有變化則獲取獲取hash值。代碼如下:
先是a.com下的文件cs1.html文件:
function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = '';
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:
//模擬一個簡單的參數(shù)處理操作
switch(location.hash){
case '#paramdo':
?callBack();
?break;
case '#paramset':
?//do something……
?break;
}
function callBack(){
try {
?parent.location.hash = 'somedata';
} catch (e) {
?// ie、chrome的安全機(jī)制無法修改parent.location.hash,
?// 所以要利用一個中間的cnblogs域下的代理iframe
?var ifrproxy = document.createElement('iframe');
?ifrproxy.style.display = 'none';
?ifrproxy.src = ''; ? ?// 注意該文件在"a.com"域下
?document.body.appendChild(ifrproxy);
}
}
a.com下的域名cs3.html
//因為parent.parent和自身屬于同一個域,所以可以改變其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);
當(dāng)然這樣做也存在很多缺點(diǎn),諸如數(shù)據(jù)直接暴露在了url中,數(shù)據(jù)容量和類型都有限等……
4、window.name實現(xiàn)的跨域數(shù)據(jù)傳輸
文章較長列在此處不便于閱讀,詳細(xì)請看?window.name實現(xiàn)的跨域數(shù)據(jù)傳輸。
5、使用HTML5 postMessage
HTML5中最酷的新功能之一就是?跨文檔消息傳輸Cross Document Messaging。下一代瀏覽器都將支持這個功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已經(jīng)使用了這個功能,用postMessage支持基于web的實時消息傳遞。
otherWindow.postMessage(message, targetOrigin);
otherWindow:?對接收信息頁面的window的引用。可以是頁面中iframe的contentWindow屬性;window.open的返回值;通過name或下標(biāo)從window.frames取到的值。
message:?所要發(fā)送的數(shù)據(jù),string類型。
targetOrigin:?用于限制otherWindow,“*”表示不作限制
a.com/index.html中的代碼:
iframe id="ifr" src="b.com/index.html"/iframe
script type="text/javascript"
window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = ''; ?// 若寫成''效果一樣 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 若寫成''就不會執(zhí)行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
/script
b.com/index.html中的代碼:
script type="text/javascript"
window.addEventListener('message', function(event){
?// 通過origin屬性判斷消息來源地址
?if (event.origin == '') {
? ? ?alert(event.data); ? ?// 彈出"I was there!"
? ? ?alert(event.source); ?// 對a.com、index.html中window對象的引用
? ? ? ? ? ? ? ? ? ? ? ? ? ?// 但由于同源策略,這里event.source不可以訪問window對象
?}
}, false);
/script
參考文章:《精通HTML5編程》第五章——跨文檔消息機(jī)制、
6、利用flash
這是從YUI3的IO組件中看到的辦法,具體可見。
可以看在Adobe Developer Connection看到更多的跨域代理文件規(guī)范:ross-Domain Policy File Specifications、HTTP Headers Blacklist。
js跨域就是使用js訪問iframe里的不同域名下的頁面內(nèi)容
由于處于安全性的考慮,瀏覽器禁止js跨域訪問,想要實現(xiàn)跨域需要那個域名下的網(wǎng)頁給予你支持才行(不然安全性就沒有保證了)
具體實現(xiàn)跨域的方法有很多中,你自己上網(wǎng)上找一找吧,有源碼的
什么情況下才會出現(xiàn)跨域?
假設(shè)域名是:
如果所請求的域名跟這個域名不致,這種情況就是跨域,由于跨域存在漏洞,所以一般來說正常的跨域請求方式是請求不到的。
解決方式:
一、window.name
1、
服務(wù)器返回
復(fù)制代碼
代碼如下:
scriptwindow.name='{"id":"3",
"name":"leisure"}';/script
2、定義一個iframe,添加onload事件
iframe
id="iframe1"
onload="iLoad"iframe
script
type="text/javascript"
var
load
=
false;
function
iLoad()
{
if(load
==
false)
{
//
同域處理,請求后會再次重新加載iframe
document.getElementById('iframe1').contentWindow.location
=
'/';
load
=
true;
}
else
{
//
獲取window.name的內(nèi)容,注意必須進(jìn)行同域處理后方可訪問!
var
data
=
document.getElementById('iframe1').contentWindow.name;
alert(data);
//
{"id":"3",
"name":"leisure"}
load
=
false;
}
}
/script
3、定義一個form,設(shè)置form的target為iframe的id,然后提交form
復(fù)制代碼
代碼如下:
form
action="url"
method="POST"
target="iframe1"
button
type="submit"
value="submit"
/
/form
二、JSONP
服務(wù)器返回
callback({"id":
"3",
"name":
"leisure"});
復(fù)制代碼
代碼如下:
script
type="text/javascript"
function
callback(data)
{
alert(data);
}
/script
script
type="text/javascript"
src=";jsonp=callback"/script
三、jQuery.getJSON
服務(wù)器返回
json格式數(shù)據(jù)
test({"id":
"3",
"name":
"leisure"});
test函數(shù)名為callback參數(shù)中定義
復(fù)制代碼
代碼如下:
$.getJSON(url
+
"?callback=?",
data,
function(data)
{
}
注意callback=?這個參數(shù)必須帶上,jquery會自動生成一個函數(shù)名替換這個問號!jQuery.getJSON實際上是用了JSONP方式實現(xiàn)。
四、flash跨域
服務(wù)器添加crossdomain.xml
復(fù)制代碼
代碼如下:
?xml
version="1.0"?
cross-domain-policy
allow-access-from
domain="*.another.com.cn"
/
/cross-domain-policy
一、一些概念
①傳統(tǒng)Ajax:交互的數(shù)據(jù)格式——自定義字符串或XML描述;
跨域——通過服務(wù)器端代理解決。
②如今最優(yōu)方案:使用JSON格式來傳輸數(shù)據(jù),使用JSONP來跨域。
③JSON:一種數(shù)據(jù)交換格式。基于純文本、被原生JS支持。
格式:兩種數(shù)據(jù)類型描述符:大括號{
}、方括號[
]。分隔符逗號、映射符冒號、定義符雙引好。
④JSONP:一種跨域數(shù)據(jù)交互協(xié)議,非官方。
1、Web頁面調(diào)用js文件,可跨域。擴(kuò)展:但凡有src屬性的標(biāo)簽都具有跨域能力。
2、跨域服務(wù)器
動態(tài)生成數(shù)據(jù)
并存入js文件(通常json后綴),供客戶端
調(diào)用。
3、為了便于客戶端使用數(shù)據(jù),形成一個非正式傳輸協(xié)議,稱為JSONP。該協(xié)議重點(diǎn)是允許用戶傳遞一個callback參數(shù)給服務(wù)器,然后服務(wù)器返回數(shù)據(jù)時
將此callback參數(shù)作為函數(shù)名包裹住JSON數(shù)據(jù),使得客戶端可以隨意定制自己的函數(shù)來自動處理返回數(shù)據(jù)。
二、JSONP實現(xiàn)
實例1——客戶端單方面接收:
①客戶端——在客戶端設(shè)置創(chuàng)建一個函數(shù)對象,名稱可為callFunc,用于接收服務(wù)器的js數(shù)據(jù)和對其進(jìn)行處理。
js數(shù)據(jù)中的核心是:調(diào)用callFunc函數(shù)的同時附帶著參數(shù),此參數(shù)即data對象的值。
復(fù)制代碼
代碼如下:
script
type="text/javascript"
var
callFunc
=
function(data){
alert('遠(yuǎn)程js文件傳來的數(shù)據(jù):'
+
data.result);//data為服務(wù)器端的JSON數(shù)據(jù)對象。
};
/script
script
type="text/javascript"
src="http://其他域的js文件.com/remote.js"/script
②服務(wù)器端——直接調(diào)用客戶端js中的函數(shù),并傳入數(shù)據(jù)。
復(fù)制代碼
代碼如下:
callFunc({"result":"value1"});
實例2——客戶端向服務(wù)器傳送
指定函數(shù)名,服務(wù)器端接收該函數(shù)名
并調(diào)用對應(yīng)函數(shù)
將數(shù)據(jù)以參數(shù)形式傳入。
復(fù)制代碼
代碼如下:
script
type="text/javascript"
//
得到航班信息查詢結(jié)果后的回調(diào)函數(shù)
var
flightHandler
=
function(data){
alert('你查詢的航班結(jié)果是:票價
'
+
data.price
+
'
元,'
+
'余票
'
+
data.tickets
+
'
張。');
};
//
動態(tài)添加鏈接服務(wù)器js文件的script。
//
在url地址中傳遞了一個code參數(shù)匹配JSON數(shù)據(jù)中的某個key,callback參數(shù)則告訴服務(wù)器:本地回調(diào)函數(shù)名為callFuncName。
var
url
=
";callback=callFuncName";
var
script
=
document.createElement('script');
script.setAttribute('src',
url);
//
將script元素在網(wǎng)頁加載時插入head頭部
document.getElementsByTagName('head')[0].appendChild(script);
/script
總結(jié):實現(xiàn)的代碼并不復(fù)雜,但在實現(xiàn)Ajax跨域、frameset/iframe跨域等卻是效率頗高的。
一般是用iframe設(shè)置
document.domain?=?'a.com';
var?ifr?=?document.createElement('iframe');
ifr.src?=?'';
ifr.style.display?=?'none';
document.body.appendChild(ifr);
ifr.onload?=?function(){
var?doc?=?ifr.contentDocument?||?ifr.contentWindow.document;
console.log(doc.documentElement.innetHTML);
};
然后HTML5新特性有 ,postMessage
function?Init?()?{????
if?(window.addEventListener)?{
//?all?browsers?except?IE?before?version?9????
window.addEventListener?("message",?OnMessage,?false);????
}????
else?{????
if?(window.attachEvent)?{
//?IE?before?version?9????
window.attachEvent("onmessage",?OnMessage);????
}????
}????
}????
function?GetState?()?{????
var?frame?=?document.getElementById?("myFrame");????
var?message?=?"getstate";//參數(shù)
if?(frame.contentWindow.postMessage)?{
//傳遞的參數(shù),后面是傳遞的你的跨域域名
frame.contentWindow.postMessage?(message,?"*");????
}????????
}????
function?OnMessage?(event)?{????
console.log(event.data);
}????
document.body.onload=function(){Init();GetState();};
ajax或者iframe指向的地址中,二級域名、端口、協(xié)議必須與主頁面完全相同,否則就算跨域
比如
a.baidu.com訪問b.baidu.com 是跨域;
a.baidu.com:8080訪問a.baidu.com:80 是跨域;
訪問 是跨域
ajax跨域,兩種辦法:后端寫個代理接口,讓后端去抓數(shù)據(jù);或者與對方合作,用jsonp等方式傳送數(shù)據(jù)
iframe跨域問題有點(diǎn)多,必須要得到iframe內(nèi)部頁面的配合才可能通信,方法也比較多:
1,假寫hash值通信,父子頁面各自建立輪詢?nèi)z測iframe中url的hash值,通過值來通信
2,利用HTML5的postMessage,不過注意這個也是異步的
3,利用IE6\7中對navigator的bug,我前同事發(fā)現(xiàn)的,在ie6/7中,父子頁面使用的window.navigator是同一個東西,父頁面改了,子頁面也會跟著變;
4,iframe中嵌套一層與頂層頁面同域的頁面,比如a中套b,b中套c,其中a、c同域,b做出改變后通過url給c傳值,c中操作top對象也就是a,由于同域,所以不會有問題
名稱欄目:跨域javascript,跨域立案什么意思
URL分享:http://chinadenli.net/article31/dsgsjsd.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、解決方案、自適應(yīng)網(wǎng)站、軟件開發(fā)、全網(wǎng)營銷推廣、品牌網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)