ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript_javascript スキルにおける 2 つのクロスドメイン技術の包括的な紹介

JavaScript_javascript スキルにおける 2 つのクロスドメイン技術の包括的な紹介

WBOY
WBOYオリジナル
2016-05-16 16:52:101305ブラウズ

このポリシーは、JavaScript コードがアクセスできるページ コンテンツに重要な制限を設けます。つまり、JavaScript は、それを含むドキュメントと同じドメイン内のコンテンツにのみアクセスできます。

JavaScript セキュリティ戦略は、Ajax プログラミングだけでなく、マルチ iframe またはマルチウィンドウ プログラミングを実行する場合にも特に重要です。このポリシーによれば、baidu.com のページに含まれる JavaScript コードは、google.com ドメイン名のページ コンテンツにアクセスできません。また、異なるサブドメイン間のページであっても、JavaScript コードを介して相互にアクセスすることはできません。 Ajax への影響は、XMLHttpRequest によって実装された Ajax リクエストが別のドメインにリクエストを送信できないことです。たとえば、abc.example.com の下にあるページは、def.example.com などに Ajax リクエストを送信できません。

しかし、詳細なフロントエンドプログラミングを行う場合、クロスドメイン操作が必然的に必要になるため、この時点で「同一生成元ポリシー」は厳しすぎます。この記事では、この問題に関するクロスドメインに必要ないくつかのテクノロジーをまとめます。

以下では、クロスドメイン テクノロジーを 2 つの状況で説明します。最初に、異なるサブドメインのクロスドメイン テクノロジーについて説明し、次に完全に異なるドメインのクロスドメイン テクノロジーについて説明します。

(1) 異なるサブドメイン内のクロスドメイン テクノロジー。

2 つの問題について個別に説明します。1 つ目は、異なるサブドメイン間で JavaScript 呼び出しを行う方法であり、2 つ目は、異なるサブドメインに Ajax リクエストを送信する方法です。

まず最初の問題を解決しましょう。example.com ドメインの下に abc.example.com と def.example.com という 2 つの異なるサブドメインがあるとします。ここで、def.example.com の下に JavaScript 関数を定義するページがあるとします。

コードをコピーします コードは次のとおりです。
function funcInDef() {
.....
}

abc.example.com の下のページで上記の関数を呼び出したいとします。議論したい abc.example.com の下のページが iframe の形式で def.example.com の下のページに埋め込まれていると仮定します。この場合、iframe で次の呼び出しを試みることができます。 >

コードをコピー コードは次のとおりです:
window.top.funcInDef();
わかりました。この呼び出しは前述の「同一生成元ポリシー」によって禁止されており、JavaScript エンジンは直接例外をスローします。
上記の呼び出しを実装するには、2 つのページのドメイン属性を変更することで実行できます。たとえば、次の JavaScript コード スニペットを abc.example.com と def.example.com の上の 2 つのページの先頭に追加できます:

Copy Code コードは次のとおりです:
document.domain = "example.com";
このようにして、2 つのページは同じドメインになり、以前の呼び出しは正常に実行できるようになります。


ここで注意すべき点は、ページの document.domain 属性は上位レベルのドメイン名 (第 1 レベルのドメイン名を除く) にのみ設定でき、サブドメインには設定できないことです。現在のドメイン名よりも深い。たとえば、abc.example.com ページのドメインは example.com にのみ設定でき、sub.abc.example.com には設定できません。もちろん、第 1 レベルのドメイン名 com に設定することはできません。

上の例では、2 つのページが iframe のネストされた関係に属している場合について説明しています。2 つのページにオープンとオープンの関係がある場合、原理はまったく同じです。

2 番目の問題、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; 工場.length; i ) {
試してみてください。 > null を返します;
}

上記のコードは、IE6 シリーズ ブラウザとの互換性を保つために ActiveXObject を参照しています。 newRequest 関数を呼び出すたびに、新しく作成された Ajax オブジェクトを取得し、この Ajax オブジェクトを使用して HTTP リクエストを送信します。たとえば、次のコードは GET リクエストを abc.example.com に送信します。
コードをコピーします コードは次のとおりです。

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 関数の定義をこのクロスドメイン ファイルに移動します。ドキュメントのドメイン値は前と同じです。crossdomain.html ファイルの先頭と、abc.example.com ドメインの下で Ajax を呼び出すページに、

コードをコピーします コードは次のとおりです:
document.domain = "example.com";

クロスを使用するには、ドメイン ファイルの場合、abc.example.com ドメインの下で Ajax を呼び出します。 ページにクロスドメイン ファイルを指す非表示の iframe を埋め込みます。たとえば、次のようにします。

コードをコピーします コードは次のとおりです:


現時点では、abc.example.com ドメイン配下のページとクロスドメイン ファイルcrossdomain.html は両方とも同じ配下にあります。ドメイン (example.com)。 abc.example.com ドメインの下のページで、

この方法で取得したリクエスト オブジェクトは、 http://def.example.com への HTTP リクエスト。

(2) 全く異なるドメインにおけるクロスドメイン技術。

トップレベルのドメイン名が異なる場合、たとえば example1.com と example2.com が JavaScript を介してフロントエンドで通信したい場合、必要なテクノロジはより複雑になります。

異なるドメインのクロスドメイン テクノロジを説明する前に、以下で説明するテクノロジが異なるサブドメインにわたる以前の状況にも適用できることをまず明確にします。クロスドメインの問題の特殊なケースのみです。もちろん、適切な状況下で適切なテクノロジーを使用すると、より高い効率とより高い安定性を確保できます。

つまり、さまざまなクロスドメイン要件に応じて、クロスドメイン テクノロジは次のカテゴリに分類できます。
1. JSONP クロスドメイン GET リクエスト
2. iframe
3. Flash クロスドメイン HTTP リクエスト
4. window.postMessage
以下では、さまざまなテクノロジーについて詳しく紹介します。

1. JSONP。
ページ内に <script> ノードを作成して異なるドメインに HTTP リクエストを送信する方法は、JSONP と呼ばれます。このテクノロジは、ドメイン間での Ajax リクエストの送信の問題を解決します。 JSONP の動作原理は次のとおりです。 <br> GET リクエストが http://example1.com/index.php ページ内の http://example2.com/getinfo.php に送信されると仮定すると、次の JavaScript コードを http://example1.com/index.php ページに配置して実装します: </strong><br><br></p> <div class="codetitle"> <span>コードをコピー<a style="CURSOR: pointer" data="91817" class="copybut" id="copybut91817" onclick="doCopy('code91817')"><u></u>コードは次のとおりです。</a></span>var eleScript= document.createElement("script");</div>eleScript.type = "text/javascript";<div class="codebody" id="code91817">eleScript.src = "http://example2. com/getinfo.php"; <br>document.getElementsByTagName("HEAD")[0].appendChild(eleScript);<br> <p>当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。<br><br>JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。<br><br>JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。</p> <p><strong>2. 通过iframe实现跨域。<br><br></strong>iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。<br><br>与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" ?> <br><クロスドメインポリシー><br> <allow-access-fromdomain="example2.com" /><br></クロスドメインポリシー><br> </div> <p><strong>4. window.postMessage<br></strong> window.postMessage は、HTML 標準の次のバージョンである HTML5 でサポートされる新機能です。現在のインターネット技術の急速な進歩の影響を受けて、ブラウザーのクロスドメイン通信に対する需要はますます高まっており、HTML 標準ではついにクロスドメイン通信が考慮されています。しかし、現時点では HTML5 はまだドラフトにすぎません。 <br> window.postMessage は、直接クロスドメイン通信を実装するための安全な方法です。ただし、現在すべてのブラウザがこの呼び出しをサポートしているわけではありません。Firefox 3、Safari 4、および IE8 のみがこの呼び出しをサポートしています。 <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">otherWindow.postMessage(message, targetOrigin);</div> <br>受信ウィンドウで、送信されたメッセージを受信するイベント処理関数を設定する必要があります。<br> <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">window.addEventListener("message", acceptMessage, false);<br>function acceptMessage(event) {<br> if (event .origin !== "http://example.org:8080") return;<br>}</div> <br>メッセージには 3 つの属性が含まれます: data、オリジン (送信ウィンドウが配置されているドメインの実際の情報を運ぶ) とソース (送信ウィンドウのハンドルを表す) です。 <br><br>セキュリティに関する考慮事項: window.postMessage を使用する場合は、メッセージの送信元属性とソース属性を使用して送信者の身元を確認する必要があります。そうしないと、XSS 脆弱性が発生します。 <br><br>window.postMessage は、iframe によって実装されたクロスドメイン機能と同じくらい強力で、使いやすく効率的ですが、ブラウザの互換性の点で現時点では改善の必要があるという欠点があります。 <br><br>原文に追加する必要があるのは、IE6 および IE7 では、オブジェクトまたは関数に割り当てられる IE の Opener の脆弱性が悪用される可能性があり、postMessage ソリューションの補足ソリューションが提供されていることです。 <br>メインページ: <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><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" ><br><html xmlns="http://www.w3.org/1999/xhtml"><br><head><br> <title>クロスドメイン</title><br>&lt ;/head><br><body><br> <iframe src="http://sh-tanzhenlin/CrossDomain-child.html"<BR> frameborder="0"visible="false" height=" 0" width="0" id="ifrChild"></iframe><br><br> <script type="text/javascript"><br> var child = document.getElementById("ifrChild" );<br> var openerObject = {<br> funcInParent:function(arg){<br> alert(arg);<br> alter('親の関数によって実行されるページ');<br> }<br> }<br><br> if(! 'v1' && !'1'[0]){ //テストブラウザは ie6 または ie7 <br> // クラック<br> child.contentWindow.opener = openerObject;<br> }<br> else{<br> //postMessage showtime<br> }<br><br> function onClick(){<br> //debugger;<br> openerObject.funcInIframe('親ページからのデータ') ;<br> }<br> </script>



用 iframe 内嵌其它ドメイン下の页面:

复制代码代码如下:








注: postMessage 方式は現在、さまざまな新しい視聴者からのサポートを、予想外の速度で取得できるようになっており、慎重に検討してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:JavaScriptのディープコピーとシャローコピーの2つの方法 array_javascriptスキル次の記事:JavaScriptのディープコピーとシャローコピーの2つの方法 array_javascriptスキル

関連記事

続きを見る