首頁 web前端 js教程 JavaScript兩種跨域技術全面介紹_javascript技巧

JavaScript兩種跨域技術全面介紹_javascript技巧

May 16, 2016 pm 04:52 PM
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函數:

複製程式碼 程式碼如下:
function funcInDef() {
    .....
}

我們想要在abc.example.com下的某個頁面中呼叫上面的函數。再假設我們要討論的abc.example.com下面的這個頁面是以iframe形式嵌入在def.example.com下面那個頁面裡的,這樣我們可能試圖在iframe裡做如下調用:

複製程式碼 程式碼如下:
window.top.funcInDef();

好,我們注意到,這個呼叫是被前面講到的「同源策略」所禁止的,JavaScript引擎會直接拋出一個異常。
為了實現上述調用,我們可以透過修改兩個頁面的domain屬性的方法來做到。例如,我們可以將上面在abc.example.com和def.example.com下的兩個頁面的頂端都加上如下的JavaScript程式碼片段:
複製代碼 程式碼如下:
document.domain = "example.com";

這樣,兩個頁面就變成同域了,前面的呼叫也可以正常執行了。

這裡要注意的一點是,一個頁面的document.domain屬性只能設定成一個更頂級的網域(除了一級網域),但不能設定成比目前網域更深層的子網域。例如,abc.example.com的頁面只能將它的domain設定成example.com,不能設定成sub.abc.example.com,當然也不能設定成一級網域com。

上面的例子討論的是兩個頁面屬於iframe嵌套關係的情況,當兩個頁面是打開與被打開的關係時,原理也完全一樣。

下面我們來解決第二個問題:如何向不同子網域提交Ajax請求。
通常情況下,我們會用與下面類似的程式碼來建立一個XMLHttpRequest物件:

複製程式碼 程式碼如下:
factories = [function() {
    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。

利用在頁面中建立<script>節點的方法向不同網域提交HTTP請求的方法稱為JSONP,這項技術可以解決跨域提交Ajax請求的問題。 JSONP的工作原理如下所述:<a style="CURSOR: pointer" data="91817" class="copybut" id="copybut91817" onclick="doCopy('code91817')">假設在http://example1.com/index.php這個頁面中向http://example2.com/getinfo.php提交GET請求,我們可以將下面的JavaScript程式碼放在http://example1.com/index.php這個頁面來實作:<U></script>
複製程式碼


程式碼如下:
var eleScript= document.createElement("script");eleScript.type = "text/javascript";eleScript.src = "http://example2.com/getinfo.php"; document.getElementsByTagName("HEAD")[0].appendChild(eleScript);

当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>&lt ;/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 方式正考慮以方便的速度得到各種新瀏覽器的支持,應可接受的商品。
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1658
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

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

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

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

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

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

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

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

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

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

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

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

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

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

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

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

See all articles