JavaScript兩種跨域技術全面介紹_javascript技巧
這個策略對於JavaScript程式碼能夠存取的頁面內容做了很重要的限制,即JavaScript只能存取與包含它的文件在同一網域下的內容。
JavaScript這個安全策略在進行多iframe或多視窗程式設計、以及Ajax程式設計時顯得格外重要。根據這個策略,在baidu.com下的頁面中包含的JavaScript程式碼,不能存取在google.com網域下的頁面內容;甚至不同的子網域之間的頁面也不能透過JavaScript程式碼互相存取。對於Ajax的影響在於,透過XMLHttpRequest實現的Ajax請求,不能向不同的網域提交請求,例如,在abc.example.com下的頁面,不能向def.example.com提交Ajax請求,等等。
然而,當進行一些比較深入的前端編程的時候,不可避免地需要進行跨域操作,這時候「同源策略」就顯得過於苛刻。本文就這個問題,概括了跨域所需的一些技術。
下面我們分兩種情況討論跨域技術:首先討論不同子域的跨域技術,然後討論完全不同域的跨域技術。
(一)不同子域的跨域技術。
我們分成兩個問題分別討論:第一個問題是如何跨不同子域進行JavaScript呼叫;第二個問題是如何向不同子域提交Ajax請求。
先來解決第一個問題,假設example.com網域下有兩個不同子網域:abc.example.com和def.example.com。現在假設在def.example.com下面有一個頁面,裡面定義了一個JavaScript函數:
.....
}
我們想要在abc.example.com下的某個頁面中呼叫上面的函數。再假設我們要討論的abc.example.com下面的這個頁面是以iframe形式嵌入在def.example.com下面那個頁面裡的,這樣我們可能試圖在iframe裡做如下調用:
好,我們注意到,這個呼叫是被前面講到的「同源策略」所禁止的,JavaScript引擎會直接拋出一個異常。
為了實現上述調用,我們可以透過修改兩個頁面的domain屬性的方法來做到。例如,我們可以將上面在abc.example.com和def.example.com下的兩個頁面的頂端都加上如下的JavaScript程式碼片段:
這樣,兩個頁面就變成同域了,前面的呼叫也可以正常執行了。
這裡要注意的一點是,一個頁面的document.domain屬性只能設定成一個更頂級的網域(除了一級網域),但不能設定成比目前網域更深層的子網域。例如,abc.example.com的頁面只能將它的domain設定成example.com,不能設定成sub.abc.example.com,當然也不能設定成一級網域com。
上面的例子討論的是兩個頁面屬於iframe嵌套關係的情況,當兩個頁面是打開與被打開的關係時,原理也完全一樣。
下面我們來解決第二個問題:如何向不同子網域提交Ajax請求。
通常情況下,我們會用與下面類似的程式碼來建立一個XMLHttpRequest物件:
return new XMLHttpRequest();
},
function() {
>},
function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}];
function newRequest() {
for (var i = 0 i & lt; factories.length; i ) {
try {
} catch(e) {}
}
return null;
}
上面的程式碼中引用ActiveXObject,是為了相容於IE6系列瀏覽器。每次我們呼叫newRequest函數,就獲得了一個剛剛建立的Ajax對象,然後用這個Ajax物件來發送HTTP請求。例如,下面的程式碼向abc.example.com發送了一個GET請求:
var request = newRequest();
request.open("GET", "http://abc.example.com" );
request.send(null);
假設上面的程式碼包含在一個abc.example.com網域下的頁面裡,則這個GET請求可以正常發送成功,沒有任何問題。然而,如果現在要向def.example.com發送請求,則出現跨域問題,JavaScript引擎拋出例外。
解決的方法是,在def.example.com域下放置一個跨域文件,假設叫crossdomain.html;然後將前面的newRequest函數的定義移到這個跨域文件中;最後像之前修改document. domain值的做法一樣,在crossdomain.html檔案和abc.example.com域下呼叫Ajax的頁面頂端,都加上:
程式碼如下:
document.domain = "example.com";複製代碼
複製程式碼
程式碼如下:
var request = window.frames["xd_Rerame"].new ();這樣取得的request對象,就可以向http://def.example.com發送HTTP請求了。
(二)完全不同域的跨域技術。
如果頂級網域都不相同,例如example1.com和example2.com之間想透過JavaScript在前端通信,則所需要的技術更複雜些。
在講解不同域的跨域技術之前,我們先明確一點,下面要講的技術也同樣適用於前面跨不同子域的情況,因為跨不同子域只是跨域問題的一個特例。當然,在適當的情況下使用適當的技術,能夠確保更優的效率和更高的穩定性。
簡言之,根據不同的跨域需求,跨域技術可以歸為下面幾類:
1、JSONP跨域GET請求
2、透過iframe實現跨域 3、flash跨域HTTP請求
4、window.postMessage以下詳細介紹各種技術。
1. JSONP。
程式碼如下:
当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。
JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2. 通过iframe实现跨域。
iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。
与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在http://example1.com/index.php页面中创建指向http://example2.com/getinfo.php的iframe节点跨域提交GET请求。然而,请求返回的结果无法回调http://example1.com/index.php页面中的callback函数,因为受到“同源策略”的影响。<br><br>为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是http://example1.com/crossdomain.html。<br><br>当http://example2.com/getinfo.php这个请求返回结果的时候,它大体上有两个选择。<br>第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件http://example1.com/crossdomain.html,同时将返回结果经过URL编码之后作为参数缀在跨域文件URL后面,例如http://example1.com/crossdomain.html?result=<URL-Encoding-Content>。<br><br>另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。<br><br>在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的http://example1.com/index.php页面中的一个预先约定好的callback函数,同时将结果参数传给这个函数。http://example1.com/index.php页面和跨域文件是在同一个域下的,因此这个函数调用可以通过。跨域文件所在iframe和原来的http://example1.com/index.php页面的关系,在前述第一种选择下,后者是前者的父窗口,在第二种选择下,后者是前者的父窗口的父窗口。<br><br>根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。<br><br>既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。<br><br>使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。</p>
<p><strong>3. 利用flash实现跨域HTTP请求<br></strong><br>据称,flash在浏览器中的普及率高达90%以上。<br><br>flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。<br>例如,我们用浏览器访问http://example1.com/index.php这个页面,在这个页面中引用了http://example2.com/flash.swf这个flash文件,然后在flash代码中向http://example3.com/webservice.php发送HTTP请求。<br><br>这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="91153" class="copybut" id="copybut91153" onclick="doCopy('code91153')"><u>複製程式碼</u></a></span> 程式碼如下:</div>
<div class="codebody" id="code91153">
<br><?xml version="1.0" ><cross-domain-policy><br> <allow-access-from domain="example2.com"></allow-access-from><br></cross-domain-policy><br><br>
</div>
<p>4. window.postMessage<strong><br> window.postMessage是HTML標準的下一個版本HTML5支援的新功能。受目前網路技術突飛猛進的影響,瀏覽器跨域通訊的需求越來越強烈,HTML標準終於把跨域通訊考慮進去了。但目前HTML5仍然只是一個draft。 </strong> window.postMessage是一個安全的實作直接跨域通訊的方法。但目前並不是所有瀏覽器都能支持,只有Firefox 3、Safari 4和IE8可以支援這個呼叫。 <br><br>使用它向其它視窗發送訊息的呼叫方式大概如下:<br><br></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="66586" class="copybut" id="copybut66586" onclick="doCopy('code66586')">複製程式碼<u></u></a></span>複製程式碼</div>
<div class="codebody" id="code66586"></div> 程式碼<br><br>otherWindow.postMessage(message, targetOrigin);<div class="codetitle">
<span>在接收的窗口,需要設定一個事件處理函數來接收發過來的訊息:<a style="CURSOR: pointer" data="40287" class="copybut" id="copybut40287" onclick="doCopy('code40287')"><u></u></a></span>複製程式碼</div>
<div class="codebody" id="code40287">
<br> 程式碼如下:<br><br>window.addEventListener("message", receiveMessage, false);}<br><br>訊息包含三個屬性:data、origin(攜帶發送視窗所在網域的真實資訊)和source (代表發送視窗的handle)。 <br><br>安全性考量:使用window.postMessage,必需要使用訊息的origin和source屬性來驗證傳送者的身份,否則會造成XSS漏洞。 <br><br>window.postMessage在功能上同iframe實現的跨域功能同樣強大,並且使用簡單,效率更高,但缺點是它目前在瀏覽器兼容方面有待提高。 <br><br>需要對原文補充的是,在IE6,IE7下可利用IE的Opener可賦值為Object或Function的漏洞,提供postMessage方案的補充方案:主頁:<p>
</p>
<div class="codetitle"><span><a style="CURSOR: pointer" data="92626" class="copybut" id="copybut92626" onclick="doCopy('code92626')"><u></u>複製程式碼</a></span></div> 程式碼如下:<div class="codebody" id="code92626">
<br> <br><br><br> <title>跨域</title>
<br>< ;/head><br><br> <iframe src="http://sh-tanzhenlin/CrossDomain-child.html"> frameborder="0"visible="false"height=" 0" width="0"visible="false"height="0" width="0"visible="false"height="0" width="0" id="ifrChild"></iframe><br><br> <script type="text/javascript"><BR> var child = document.getElement > funcInParent:function(arg){<BR> alert('由父親頁面中的函數執行') ;<BR> }<BR> }< v1' && !'1'[0]){ //測試瀏覽器是ie6或ie7 <BR> //破解<BR> <BR> else{<br> //postMessage showtime<br> }<BR><BR> function onClick(){<BR> openerObject.funcInIframe('來自父親頁面的資料') ;<BR> }<BR> </script>
用iframe內嵌其他網域下的頁面:
程式碼如下:
onload = function(){
地alert(arg);
alert('由函數執行在iframe 中');
}
window.opener.funcInParent('來自iframe 的數據')
}
}
>
註:postMessage 方式正考慮以方便的速度得到各種新瀏覽器的支持,應可接受的商品。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
