JS跨域問(wèn)題詳解
JavaScript是一種在Web開(kāi)發(fā)中經(jīng)常使用的前端動(dòng)態(tài)腳本技術(shù)。在JavaScript中,有一個(gè)很重要的安全性限制,被稱為“Same-Origin Policy”(同源策略)。這一策略對(duì)于JavaScript代碼能夠訪問(wèn)的頁(yè)面內(nèi)容做了很重要的限制,即JavaScript只能訪問(wèn)與包含它的文檔在同一域下的內(nèi)容。
JavaScript這個(gè)安全策略在進(jìn)行多iframe或多窗口編程、以及Ajax編程時(shí)顯得尤為重要。根據(jù)這個(gè)策略,在baidu.com下的頁(yè)面中包含的JavaScript代碼,不能訪問(wèn)在google.com域名下的頁(yè)面內(nèi)容;甚至不同的子域名之間的頁(yè)面也不能通過(guò)JavaScript代碼互相訪問(wèn)。對(duì)于Ajax的影響在于,通過(guò)XMLHttpRequest實(shí)現(xiàn)的Ajax請(qǐng)求,不能向不同的域提交請(qǐng)求,例如,在abc.example.com下的頁(yè)面,不能向def.example.com提交Ajax請(qǐng)求,等等。
然而,當(dāng)進(jìn)行一些比較深入的前端編程的時(shí)候,不可避免地需要進(jìn)行跨域操作,這時(shí)候“同源策略”就顯得過(guò)于苛刻。本文就這個(gè)問(wèn)題,概括了跨域所需要的一些技術(shù)。
下面我們分兩種情況討論跨域技術(shù):首先討論不同子域的跨域技術(shù),然后討論完全不同域的跨域技術(shù)。
(一)不同子域的跨域技術(shù)。
我們分兩個(gè)問(wèn)題來(lái)分別討論:第一個(gè)問(wèn)題是如何跨不同子域進(jìn)行JavaScript調(diào)用;第二個(gè)問(wèn)題是如何向不同子域提交Ajax請(qǐng)求。
先來(lái)解決第一個(gè)問(wèn)題,假設(shè)example.com域下有兩個(gè)不同子域:abc.example.com和def.example.com?,F(xiàn)在假設(shè)在def.example.com下面有一個(gè)頁(yè)面,里面定義了一個(gè)JavaScript函數(shù):
function funcInDef() {
.....
}
我們想在abc.example.com下的某個(gè)頁(yè)面里調(diào)用上面的函數(shù)。再假設(shè)我們要討論的abc.example.com下面的這個(gè)頁(yè)面是以iframe形式嵌入在def.example.com下面那個(gè)頁(yè)面里的,這樣我們可能試圖在iframe里做如下調(diào)用:
window.top.funcInDef();
好,我們注意到,這個(gè)調(diào)用是被前面講到的“同源策略”所禁止的,JavaScript引擎會(huì)直接拋出一個(gè)異常。
為了實(shí)現(xiàn)上述調(diào)用,我們可以通過(guò)修改兩個(gè)頁(yè)面的domain屬性的方法做到。例如,我們可以將上面在abc.example.com和def.example.com下的兩個(gè)頁(yè)面的頂端都加上如下的JavaScript代碼片段:
<script type="text/javascript">
document.domain = "example.com";
</script>
這樣,兩個(gè)頁(yè)面就變?yōu)橥蛄?,前面的調(diào)用也可以正常執(zhí)行了。
這里需要注意的一點(diǎn)是,一個(gè)頁(yè)面的document.domain屬性只能設(shè)置成一個(gè)更頂級(jí)的域名(除了一級(jí)域名),但不能設(shè)置成比當(dāng)前域名更深層的子域名。例如,abc.example.com的頁(yè)面只能將它的domain設(shè)置成example.com,不能設(shè)置成sub.abc.example.com,當(dāng)然也不能設(shè)置成一級(jí)域名com。
上面的例子討論的是兩個(gè)頁(yè)面屬于iframe嵌套關(guān)系的情況,當(dāng)兩個(gè)頁(yè)面是打開(kāi)與被打開(kāi)的關(guān)系時(shí),原理也完全一樣。
下面我們來(lái)解決第二個(gè)問(wèn)題:如何向不同子域提交Ajax請(qǐng)求。
通常情況下,我們會(huì)用與下面類似的代碼來(lái)創(chuàng)建一個(gè)XMLHttpRequest對(duì)象:
factories = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
function newRequest() {
for(var i = 0; i <</SPAN> factories.length; i++) {
try{
var factory = factories[i];
return factory();
} catch(e) {}
}
return null;
}
上面的代碼中引用ActiveXObject,是為了兼容IE6系列瀏覽器。每次我們調(diào)用newRequest函數(shù),就獲得了一個(gè)剛剛創(chuàng)建的Ajax對(duì)象,然后用這個(gè)Ajax對(duì)象來(lái)發(fā)送HTTP請(qǐng)求。例如,下面的代碼向abc.example.com發(fā)送了一個(gè)GET請(qǐng)求:
假設(shè)上面的代碼包含在一個(gè)abc.example.com域名下的頁(yè)面里,則這個(gè)GET請(qǐng)求可以正常發(fā)送成功,沒(méi)有任何問(wèn)題。然而,如果現(xiàn)在要向def.example.com發(fā)送請(qǐng)求,則出現(xiàn)跨域問(wèn)題,JavaScript引擎拋出異常。
解決的辦法是,在def.example.com域下放置一個(gè)跨域文件,假設(shè)叫crossdomain.html;然后將前面的newRequest函數(shù)的定義移到這個(gè)跨域文件中;最后像之前修改document.domain值的做法一樣,在crossdomain.html文件和abc.example.com域下調(diào)用Ajax的頁(yè)面頂端,都加上:
<script type="text/javascript">
document.domain = "example.com";
</script>
為了使用跨域文件,我們?cè)赼bc.example.com域下調(diào)用Ajax的頁(yè)面中嵌入一個(gè)隱藏的指向跨域文件的iframe,例如:
[code]
<iframe name="xd_iframe" style="display:none" src=">
這時(shí)abc.example.com域下的頁(yè)面和跨域文件crossdomain.html都在同一個(gè)域(example.com)下,我們可以在abc.example.com域下的頁(yè)面中去調(diào)用crossdomain.html中的newRequest函數(shù):
var request = window.frames["xd_iframe"].newRequest();
這樣獲得的request對(duì)象,就可以向http://def.example.com發(fā)送HTTP請(qǐng)求了。
(二)完全不同域的跨域技術(shù)。
如果頂級(jí)域名都不相同,例如example1.com和example2.com之間想通過(guò)JavaScript在前端通信,則所需要的技術(shù)更復(fù)雜些。
在講解不同域的跨域技術(shù)之前,我們首先明確一點(diǎn),下面要講的技術(shù)也同樣適用于前面跨不同子域的情況,因?yàn)榭绮煌佑蛑皇强缬騿?wèn)題的一個(gè)特例。當(dāng)然,在恰當(dāng)?shù)那闆r下使用恰當(dāng)?shù)募夹g(shù),能夠保證更優(yōu)的效率和更高的穩(wěn)定性。
簡(jiǎn)言之,根據(jù)不同的跨域需求,跨域技術(shù)可以歸為下面幾類:
1、JSONP跨域GET請(qǐng)求
2、通過(guò)iframe實(shí)現(xiàn)跨域
3、flash跨域HTTP請(qǐng)求
4、window.postMessage
本文先到這里,后續(xù)我們?cè)僭敿?xì)介紹上面提到的4種跨域技術(shù),稍后就奉上!
- ajax跨域請(qǐng)求js拒絕訪問(wèn)的解決方法
- js跨域訪問(wèn)示例(客戶端/服務(wù)端)
- getJSON跨域SyntaxError問(wèn)題分析
- JS不能跨域借助jquery獲取IP地址的方法
- js跨域問(wèn)題淺析及解決方法優(yōu)缺點(diǎn)對(duì)比
- 使用jsonp完美解決跨域問(wèn)題
- 5種處理js跨域問(wèn)題方法匯總
- 深入分析JSONP跨域的原理
- 詳細(xì)解密jsonp跨域請(qǐng)求
- js設(shè)置document.domain實(shí)現(xiàn)跨域的注意點(diǎn)分析
- javascript跨域方法、原理以及出現(xiàn)問(wèn)題解決方法(詳解)
相關(guān)文章
javascript數(shù)組里的27個(gè)方法總合詳解
這篇文章主要為大家詳細(xì)介紹了javascript數(shù)組里的方法27個(gè)總合,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02JavaScript中Number.MIN_VALUE屬性的使用示例
這篇文章主要介紹了JavaScript中Number.MIN_VALUE屬性的使用示例,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06JavaScript italics方法入門(mén)實(shí)例(把字符串顯示為斜體)
這篇文章主要介紹了JavaScript italics方法入門(mén)實(shí)例,italics方法用于把字符串顯示為斜體,需要的朋友可以參考下2014-10-10JavaScript 學(xué)習(xí)筆記(十四) 正則表達(dá)式
RegExp類 RegExp對(duì)象的構(gòu)造函數(shù)可以帶一個(gè)或兩個(gè)參數(shù) 第一個(gè)參數(shù)是描述需要進(jìn)行匹配的模式字符串,如果還有第二個(gè)參數(shù),這個(gè)參數(shù)則制定了額外的處理指令。2010-01-01