亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript兩種跨域技術全面介紹

2019-11-20 20:49:20
字體:
來源:轉載
供稿:網友

這一策略對于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?,F在假設在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() {
    return new ActiveXObject("Msxml2.XMLHTTP");
},
function() {
    return new ActiveXObject("Microsoft.XMLHTTP");
}];
function newRequest() {
    for (var i = 0; i & lt; factories.length; i++) {
        try {
            var factory = factories[i];
            return factory();
        } 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";


為了使用跨域文件,我們在abc.example.com域下調用Ajax的頁面中嵌入一個隱藏的指向跨域文件的iframe,例如:
復制代碼 代碼如下:
<iframe name="xd_iframe" style="display:none" src="http://def.example.com/crossdomain.html">
</iframe>


這時abc.example.com域下的頁面和跨域文件crossdomain.html都在同一個域(example.com)下,我們可以在abc.example.com域下的頁面中去調用crossdomain.html中的newRequest函數:
復制代碼 代碼如下:
var request = window.frames["xd_iframe"].newRequest();

這樣獲得的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的工作原理如下所述:
假設在http://example1.com/index.php這個頁面中向http://example2.com/getinfo.php提交GET請求,我們可以將下面的JavaScript代碼放在http://example1.com/index.php這個頁面中來實現:

復制代碼 代碼如下:
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函數,因為受到“同源策略”的影響。

為了解決這個問題,我們需要在example1.com下放置一個跨域文件,比如路徑是http://example1.com/crossdomain.html。

當http://example2.com/getinfo.php這個請求返回結果的時候,它大體上有兩個選擇。
第一個選擇是,它可以在iframe中做一個302跳轉,跳轉到跨域文件http://example1.com/crossdomain.html,同時將返回結果經過URL編碼之后作為參數綴在跨域文件URL后面,例如http://example1.com/crossdomain.html?result=<URL-Encoding-Content>。

另一個選擇是,它可以在返回的頁面中再嵌入一個iframe,指向跨域文件,同時也是將返回結果經過URL編碼之后作為參數綴在跨域文件URL后面。

在跨域文件中,包含一段JavaScript代碼,這段代碼完成的功能,是從URL中提取結果參數,經過一定處理后調用原來的http://example1.com/index.php頁面中的一個預先約定好的callback函數,同時將結果參數傳給這個函數。http://example1.com/index.php頁面和跨域文件是在同一個域下的,因此這個函數調用可以通過??缬蛭募趇frame和原來的http://example1.com/index.php頁面的關系,在前述第一種選擇下,后者是前者的父窗口,在第二種選擇下,后者是前者的父窗口的父窗口。

根據前面的敘述,有了跨域文件之后,我們就可以實現通過iframe方式在不同域之間進行JavaScript調用。這個調用過程可以完全跟HTTP請求無關,例如有些站點可以支持動態地調整在頁面中嵌入的第三方iframe的高度,這其實是通過在第三方iframe里面檢測自己頁面的高度變化,然后通過跨域方式的函數調用將這個變化告知父窗口來完成的。

既然利用iframe可以實現跨域JavaScript調用,那么跨域提交POST請求等其它類型的HTTP請求就不是難事。例如我們可以跨域調用目標域的JavaScript代碼在目標域下提交Ajax請求(GET/POST/etc.),然后將返回的結果再跨域傳原來的域。

使用iframe跨域,優點是功能強大,支持各種瀏覽器,幾乎可以完成任何跨域想做的事情;缺點是實現復雜,要處理很多瀏覽器兼容問題,并且傳輸的數據不宜過大,過大了可能會超過瀏覽器對URL長度的限制,要考慮對數據進行分段傳輸等。

3. 利用flash實現跨域HTTP請求

據稱,flash在瀏覽器中的普及率高達90%以上。

flash代碼和JavaScript代碼之間可以互相調用,并且flash的“安全沙箱”機制與JavaScript的安全機制并不盡相同,因此,我們可以利用flash來實現跨域提交HTTP請求(支持GET/POST等)。
例如,我們用瀏覽器訪問http://example1.com/index.php這個頁面,在這個頁面中引用了http://example2.com/flash.swf這個flash文件,然后在flash代碼中向http://example3.com/webservice.php發送HTTP請求。

這個請求能否被成功發送,取決于在example3.com的根路徑下是否放置了一個crossdomain.xml以及這個crossdomain.xml的配置如何。flash的“安全沙箱”會保證:僅當example3.com服務器在根路徑下確實放置了crossdomain.xml文件并且在這個文件中配置了允許接受來自example2.com的flash的請求時,這個請求才能真正成功。下面是一個crossdomain.xml文件內容的例子:

復制代碼 代碼如下:

<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="example2.com" />
</cross-domain-policy>

4. window.postMessage
  window.postMessage是HTML標準的下一個版本HTML5支持的一個新特性。受當前互聯網技術突飛猛進的影響,瀏覽器跨域通信的需求越來越強烈,HTML標準終于把跨域通信考慮進去了。但目前HTML5仍然只是一個draft。
  window.postMessage是一個安全的實現直接跨域通信的方法。但是目前并不是所有瀏覽器都能支持,只有Firefox 3、Safari 4和IE8可以支持這個調用。

使用它向其它窗口發送消息的調用方式大概如下:

復制代碼 代碼如下:
otherWindow.postMessage(message, targetOrigin);

在接收的窗口,需要設置一個事件處理函數來接收發過來的消息:
復制代碼 代碼如下:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
    if (event.origin !== "http://example.org:8080") return;
}

消息包含三個屬性:data、origin(攜帶發送窗口所在域的真實信息)和source(代表發送窗口的handle)。

安全性考慮:使用window.postMessage,必需要使用消息的origin和source屬性來驗證發送者的身份,否則會造成XSS漏洞。

window.postMessage在功能上同iframe實現的跨域功能同樣強大,并且使用簡單,效率更高,但缺點是它目前在瀏覽器兼容方面有待提高。

需要對原文補充的是,在IE6,IE7下可利用IE的Opener可賦值為Object或Function的漏洞,提供postMessage方案的補充方案:
主頁面:

復制代碼 代碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>CrossDomain</title>
</head>
<body>
    <iframe src="http://sh-tanzhenlin/CrossDomain-child.html"
        frameborder="0" visible="false" height="0" width="0" id="ifrChild"></iframe>

    <script type="text/javascript">
        var child = document.getElementById("ifrChild");
        var openerObject = {
                funcInParent:function(arg){
                    alert(arg);
                    alert('executed by a function in parent page');
                }
            }

        if(!+'/v1' && !'1'[0]){ //test browser is ie6 or ie7  
            //crack
            child.contentWindow.opener = openerObject;
        }
        else{
            //postMessage showtime
        }

        function onClick(){
            //debugger;
            openerObject.funcInIframe('data from parent page ');
        }
    </script>
    <input type="button" value="click me" onclick="onClick()" />
</body>
</html>

用iframe內嵌其它域下的頁面:

復制代碼 代碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
               <script type="text/javascript">
                        onload = function(){
                                if(!+'/v1' && !'1'[0]){ // test browser if is ie6 or ie7
                                        window.opener.funcInIframe=function(arg){
                                                alert(arg);
                                                alert('executed by a function in iframe');
                                        }
                                        window.opener.funcInParent('data from iframe')
                                }
                        }
                </script>
        </head>
        <body>
        </body>
</html>

注:postMessage方式正以意想不到的速度得到各種新瀏覽器的支持,應予以著重考慮。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一本一本久久a久久精品综合小说| 国产精品成人在线| 欧美性xxxx18| 亚洲天堂网站在线观看视频| 色综合影院在线| 国产亚洲免费的视频看| 国产精品福利在线观看网址| 孩xxxx性bbbb欧美| 精品欧美一区二区三区| 日韩一区二区精品视频| 91精品国产乱码久久久久久久久| 成人a级免费视频| 国产精品久久不能| 欧美日在线观看| 欧美激情按摩在线| 国产精品一区二区电影| 日韩精品高清视频| 精品欧美国产一区二区三区| 狠狠躁夜夜躁人人躁婷婷91| 欧美极品少妇与黑人| 亚洲日本中文字幕免费在线不卡| 在线观看欧美成人| 欧美丰满少妇xxxxx| 日韩国产精品视频| 中文字幕日韩欧美精品在线观看| 国产午夜精品一区二区三区| 5278欧美一区二区三区| 日韩男女性生活视频| 一本久久综合亚洲鲁鲁| 欧美一区二粉嫩精品国产一线天| 亚洲欧美日韩在线一区| 亚洲欧洲一区二区三区在线观看| 亚洲国产91色在线| 欧美裸体xxxx极品少妇软件| www.99久久热国产日韩欧美.com| 午夜精品久久久久久久男人的天堂| 亚洲石原莉奈一区二区在线观看| 久久久精品视频成人| 色偷偷91综合久久噜噜| 日本在线观看天堂男亚洲| 日韩av在线免费观看一区| 日韩精品有码在线观看| 日本精品久久中文字幕佐佐木| 精品久久香蕉国产线看观看gif| 在线色欧美三级视频| 亚洲欧美日韩视频一区| 久久精品99久久久香蕉| 久久久久久国产免费| 欧美一区二区影院| 欧美激情影音先锋| 亚洲最大成人网色| 国产在线日韩在线| 狠狠操狠狠色综合网| 国产精品美女视频网站| 一个人看的www久久| 国产精品18久久久久久麻辣| 78m国产成人精品视频| 欧美综合在线第二页| 日韩国产精品视频| 国产在线视频一区| 中文字幕日韩av电影| 国产拍精品一二三| 国产精品入口尤物| 亚洲精品国产精品久久清纯直播| 国产成人精品免高潮在线观看| 91免费看片网站| 欧美日韩亚洲天堂| 亚洲香蕉在线观看| 欧美激情二区三区| 久久久视频在线| 91系列在线播放| 亚洲福利精品在线| 7m精品福利视频导航| 国产日韩在线免费| 亚洲精品网站在线播放gif| 日韩在线视频国产| 中文字幕日韩有码| 亚洲精品成a人在线观看| 视频直播国产精品| 91精品国产91久久久久久最新| 日韩美女视频在线观看| 秋霞av国产精品一区| 国产精品极品美女粉嫩高清在线| 久久久99久久精品女同性| 欧美日韩国内自拍| 亚洲欧美国产精品专区久久| 亚洲第一免费网站| 亚洲国产成人av在线| 欧美另类极品videosbestfree| 日韩中文字幕亚洲| 亚洲偷熟乱区亚洲香蕉av| 国产一区视频在线播放| 久久久久久久久91| 久久综合久久八八| 国内精品久久久久久| 精品无人区太爽高潮在线播放| 精品欧美激情精品一区| 26uuu另类亚洲欧美日本一| 久久成人精品一区二区三区| 国产91成人在在线播放| 国产成人精品a视频一区www| 国产在线精品一区免费香蕉| 最新国产成人av网站网址麻豆| 亚洲免费成人av电影| 亚洲人成电影网站色xx| 亚洲va欧美va国产综合剧情| 国产成人免费av电影| 欧美国产日本高清在线| 在线观看日韩www视频免费| 91久久精品在线| 91精品国产亚洲| 91成人精品网站| 午夜精品久久久久久久久久久久| 亚洲福利在线视频| 午夜精品福利视频| 国产精品6699| 欧美亚洲成人精品| 欧美一区二区三区精品电影| 国产精品大片wwwwww| 欧美成年人视频| 亚洲免费视频一区二区| 欧美激情精品在线| 欧美激情高清视频| 亚洲精品一区二区久| 亚洲第一视频网站| 国产欧美久久一区二区| 国产成人亚洲综合| 亚洲欧洲午夜一线一品| 欧美日韩性生活视频| 一区二区三区国产视频| 伦理中文字幕亚洲| 亚洲欧美日韩一区在线| 欧美视频一区二区三区…| 黑人与娇小精品av专区| 亚洲福利视频免费观看| 91亚洲va在线va天堂va国| 日韩高清电影免费观看完整版| 欧美成人h版在线观看| 日韩大片免费观看视频播放| 国产日韩欧美一二三区| 日韩美女免费视频| xvideos亚洲人网站| 国产精品高清在线观看| 91高潮精品免费porn| 日韩免费av片在线观看| 亚洲欧美日韩成人| 国产成人精品在线播放| 国产精品美女免费视频| 精品偷拍各种wc美女嘘嘘| 久久夜色撩人精品| 国产精品a久久久久久| 国产精品成人播放| 国产精品视频区| 日韩成人av网| 在线精品国产欧美| 国产欧美精品一区二区| 欧美自拍大量在线观看| 久久久欧美一区二区| 欧美一级免费视频| 国产精品久久久久久网站| 国产亚洲欧美aaaa| 欧美黄色片免费观看| 国产精品直播网红| 国产成人精品a视频一区www|