JavaScript のクロスドメイン アクセスは、Web 開発者がよく遭遇する問題です。クロスドメインとは何ですか? あるドメインにロードされたスクリプトが別のドメインのドキュメント属性を取得または操作する JavaScript クロスドメインを実装する 3 つの方法を以下に示します。 :
1. iframe に基づくクロスドメイン実装
iframe に基づくクロスドメイン実装では、2 つのドメインが aa.xx.com、bb.xx.com の特性を持つ必要があります。つまり、2 つのページが基本ドメイン (たとえば、両方とも xxx.com) に属している必要があります。 com、または xxx .com.cn) では、同じプロトコル (たとえば、両方とも http) と同じポート (たとえば、両方とも 80) を使用して、両方のページに document.domain を同時に追加します。子ページを呼び出す親ページの機能を実現できるコードは次のとおりです:
ページ 1:
HTML コード
<html> <head> <script> document.domain = "xx.com"; function aa(){ alert("p"); } </script> </head> <body> <iframe src="http://localhost:8080/CmsUI/2.html" id="i"> </iframe> <script> document.getElementById('i').onload = function(){ var d = document.getElementById('i').contentWindow; d.a(); }; </script> </body> </html>
ページ 2:
HTML コード
<html> <head> <script> document.domain = "xx.com"; function a(){ alert("c"); } </script> </head> <body> </body> </html>
現時点では、親ページは子ページの関数を呼び出して、JS クロスドメイン アクセスを実現できます
2. スクリプトタグに基づくクロスドメイン実装
スクリプト タグ自体は他のドメインのリソースにアクセスでき、ブラウザーの同一オリジン ポリシーによって制限されません。コードは次のとおりです。
Java コード
var script = document.createElement('script'); script.src = "http://aa.xx.com/js/*.js"; document.body.appendChild(script);
この方法では、スクリプト タグを動的に作成することで他のドメインの js ファイルをロードでき、ロードされた js ファイルの関数をこのページから呼び出すことができます。この欠点は、他のドメインのドキュメントをロードできないことです。 、js ファイルのみがこの方法で実装されます。jsonp はコールバック パラメーターを他のドメインに渡し、他のドメインのバックグラウンドを介してコールバック パラメーターの値と json 文字列をパッケージ化して返します。 scriptタグ、ブラウザ 返された文字列はJavaScriptに従って解析・実行され、ドメイン間のデータ送信を実現します。
jquery での jsonp のサポートもこのソリューションに基づいています。
3.バックエンドプロキシメソッド
この方法では、すべてのクロスドメインの問題を解決できます。つまり、バックエンドがプロキシとして使用され、他のドメインの各リクエストがこのドメインのバックエンドに転送されます。このドメインのバックエンドは、http をシミュレートすることで他のドメインにアクセスします。この利点は、アクセス対象がドキュメントであっても、JS ファイルであっても、クロスドメインでアクセスできることです。
次の表は、相対 http://store.company.com/dir/page.html相同性検出結果:
クロスドメインの問題を解決するには、次のメソッドを使用できます:
1. jsonp によるクロスドメイン
js では、XMLHttpRequest を直接使用して、異なるドメイン上のデータをリクエストすることはできません。ただし、jsonp はこの機能を使用してページ上に異なるドメインの js スクリプト ファイルを導入することができます。
たとえば、a.html ページがあるとします。このページ内のコードでは、別のドメインの json データを取得するために ajax を使用する必要があります。json データのアドレスは http://example.com/data であるとします。 .php の場合、a.html のコードは次のようになります:
データを取得するためにアドレスの後にコールバック パラメーターがあることがわかります。慣例により、このパラメーター名が使用されますが、他のパラメーターも使用できます。もちろん、データを取得するための jsonp アドレス ページがあなたの管理下にない場合は、データを提供する側が指定した形式に従って運用する必要があります。
js ファイルとして導入されるため、http://example.com/data.php は実行可能な js ファイルを返す必要があるため、このページの PHP コードは次のようになります:
そのページの最終出力結果は次のとおりです:
http://example.com/data.php?callback=dosomething を通じて取得した js ファイルは、前に定義した dosomething 関数であり、そのパラメータは必要な json データです。ドメイン全体で必要なデータを取得する方法です。
このように、jsonp の原理は非常に明確です。js ファイルが script タグを通じて導入されると、url パラメーターで指定した関数が実行され、json データが渡されます。パラメータとして必要です。したがって、jsonp はサーバー側ページからの対応する連携を必要とします。
jsonp クロスドメインの原理を理解すると、スクリプト タグを手動で記述することなく、js を使用してクロスドメイン操作用のスクリプト タグを動的に生成できます。ページで jquery を使用している場合は、カプセル化されたメソッドを通じて jsonp 操作を簡単に実行できます。
原理は同じですが、手動でスクリプト タグを挿入し、コールバック関数を定義する必要がない点が異なります。 jQuery は、callback=? 内の疑問符を置き換えるグローバル関数を自動的に生成し、データを取得した後にそれを自動的に破棄します。実際には、これは一時的なプロキシ関数として機能します。 $.getJSON メソッドは、クロスドメインであるかどうかを自動的に判断し、クロスドメインでない場合は通常の ajax メソッドを呼び出します。クロスドメインである場合は、jsonp コールバック関数を非同期で呼び出します。 jsファイルを読み込んでいます。
2. document.domain
を変更してサブドメインを横断するすべてのブラウザには同一生成元ポリシーがあり、その制限の 1 つは、最初の方法で、ajax を使用して異なるソースからドキュメントをリクエストできないことです。 2 番目の制限は、js がブラウザー内の異なるドメインのフレーム間で対話できないことです。説明する必要があることの 1 つは、異なるフレームワーク (父子またはピア) が互いのウィンドウ オブジェクトを取得できることですが、厄介なのは、取得したウィンドウ オブジェクトのプロパティとメソッドを使用できないことです (HTML5 の postMessage メソッドは例外であり、ie6 などの一部のブラウザでは、top やparentなどのいくつかの属性も使用できます)。つまり、これは、ほとんど役に立たないウィンドウ オブジェクトを取得するだけであると考えることができます。たとえば、アドレスが http://www.example.com/a.html であるページがあり、このページには iframe があり、その src は http://たとえば .com/b.html では、明らかに、このページとその中の iframe は異なるドメインにあるため、ページ内に js コードを記述しても iframe のコンテンツを取得できません:
現時点では、http://www.example.com/a.html と http://example.com を追加するだけで済みます。 / b.htmlこれら 2 つのページの document.domain を同じドメイン名に設定するだけです。ただし、document.domain の設定は制限されており、document.domain はそれ自体または上位レベルの親ドメインにのみ設定でき、メイン ドメインは同じである必要があることに注意してください。例: a.b.example.com のドキュメントの document.domain は、a.b.example.com、b.example.com、example.com のいずれかに設定できますが、c.a.b.example.com には設定できません。は現在のものです。メイン ドメインはもう同じではないため、ドメインのサブドメインを baidu.com に設定することはできません。
ページ http://www.example.com/a.html で document.domain:
を設定しますページ http://example.com/b.html にも document.domain を設定します。これも必要です。このドキュメントのドメインは example.com である必要があります。 document.domain の値を設定します:
このようにして、js を通じて iframe 内のさまざまな属性やオブジェクトにアクセスできます。
しかし、http://www.example.com/a.html で ajax を介して http://example.com/b.html を直接リクエストしたい場合は、ページ ページでは、同じ document.domain を設定しても機能しないため、document.domain を変更する方法は、異なるサブドメイン内のフレーム間の対話にのみ適用されます。 ajax メソッドを通じてさまざまなサブドメインのページと対話する場合は、jsonp メソッドの使用に加えて、非表示の iframe をプロキシとして使用することもできます。原理は、この iframe に、ajax を通じてデータを取得したいターゲット ページと同じドメインのページを読み込ませることです。そのため、この iframe 内のページは、通常どおり ajax を使用して必要なデータを取得し、その後、私たちを介して取得することができます。先ほど述べた document.domain を変更すると、js を介してこの iframe を完全に制御できるようになり、iframe に ajax リクエストを送信させ、受信したデータを取得することもできます。
3. クロスドメインに window.name を使用します
window オブジェクトには name 属性があり、これには特徴があります。つまり、ウィンドウ (ウィンドウ) のライフサイクル内で、ウィンドウによってロードされるすべてのページは window.name を共有し、各ページは window.name と固有の関係を持ちます。 window.name には読み取りおよび書き込み権限があり、ウィンドウにロードされるすべてのページで永続的であり、新しいページがロードされてもリセットされません。
たとえば、次のコードを持つページ a.html があります:
b.html ページのコードをもう一度見てください:
a.html ページが読み込まれてから 3 秒後、b.html ページにジャンプし、結果は次のようになります:
前のページ a.html によって window.name に設定された値が b.html ページで正常に取得されたことがわかります。後続のロードされたすべてのページで window.name が変更されていない場合、これらすべてのページによって取得される window.name の値は、a.html ページによって設定された値になります。もちろん、必要に応じて、どのページでも window.name の値を変更できます。 window.name の値は文字列の形式のみであることに注意してください。この文字列の最大サイズはブラウザによって異なりますが、通常はこれで十分です。
上記の例では、使用したページ a.html と b.html は同じドメインにありますが、a.html と b.html が異なるドメインにある場合でも、上記の結論は当てはまります。クロスドメインに window.name を使用する原則も同様です。
window.name を通じてドメイン間でデータを取得する方法を見てみましょう。または例を挙げてください。
たとえば、www.example.com/a.html ページがある場合、a.html ページで js を使用して別のページ www.cnblogs を取得する必要があります。 com は別のドメインにあります。/data.html 内のデータ。
data.html ページのコードは非常に単純で、a.html ページが現在の window.name に対して取得したいデータ値を設定するだけです。 data.html のコード:
では、a.html ページで、data.html ページをロードするにはどうすればよいでしょうか? a.html ページがジャンプしなくても data.html 内のデータを取得したいので、a.html ページの window.location を変更して data.html ページを直接ロードすることは明らかにできません。答えは、a.html ページで非表示の iframe を使用して仲介者として機能することです。iframe は data.html からデータを取得し、次に a.html は iframe からデータを取得します。
仲介者として機能する iframe が data.html の window.name によって設定されたデータを取得したい場合は、この iframe の src を www.cnblogs.com/data.html。次に、a.html が iframe によって取得されたデータを取得したい場合、つまり iframe の window.name の値を取得したい場合は、iframe の src を a.html と同じドメインに設定する必要もあります。それ以外の場合、前述の同一生成元ポリシーに従って、a.html は iframe の window.name 属性にアクセスできません。これがクロスドメイン プロセス全体です。
a.html ページのコードを見てください:上記のコードは、最も単純な原理のデモ コードです。js を使用して、iframe の動的作成、さまざまなイベントの動的登録など、上記のプロセスをカプセル化できます。もちろん、データを取得した後は安全のためです。 、プロキシとして機能する iframe を破棄できます。インターネット上には同様の既製のコードがたくさんありますので、興味があれば探してみてください。
クロスドメインは window.name を通じて行われ、それが仕組みです。
4. HTML5 で新しく導入された window.postMessage メソッドを使用して、ドメイン間でデータを送信します
window.postMessage(message,targetOrigin) メソッドは、HTML5 で新たに導入された機能です。現在、IE8 では、ウィンドウ オブジェクトが同じオリジンに属しているか、別のオリジンに属しているかに関係なく、このメソッドを使用して他のウィンドウ オブジェクトにメッセージを送信できます。 、FireFox、Chrome、Opera などのブラウザはすでに window.postMessage メソッドをサポートしています。
postMessage メソッドを呼び出すウィンドウ オブジェクトは、メッセージを受信するウィンドウ オブジェクトを参照します。このメソッドの最初のパラメーター message は、送信されるメッセージであり、2 番目のパラメーター targetOrigin のみを指定できます。受信を制限するために使用されます。ドメインを制限したくない場合は、ワイルドカード * を使用できます。
メッセージを受信する必要があるウィンドウ オブジェクトは、自身のメッセージ イベントを監視することで受信メッセージを取得できます。メッセージの内容はイベント オブジェクトの data 属性に格納されます。
上記で説明した他のウィンドウ オブジェクトへのメッセージの送信とは、実際には、各フレームにウィンドウ オブジェクトがあるため、ページに複数のフレームがある状況を指します。 2 番目の方法について説明したときに、異なるドメインのフレームワークが互いのウィンドウ オブジェクトを取得でき、window.postMessage メソッドも使用できると述べました。 2 ページからなる簡単な例を見てみましょう
ページ a を実行した後に得られた結果:
ページ b がメッセージを正常に受信したことがわかります。
postMessage を使用してドメイン間でデータを送信するのは比較的直感的で便利ですが、IE6 と IE7 がサポートしていないという欠点があるため、これを使用するかどうかは実際のニーズによって異なります。
結論:
上記の方法以外にも、フラッシュやサーバー上にプロキシ ページを設定するなどのクロスドメインの方法もありますが、ここでは紹介しません。
上記の 4 つのメソッドは、プロジェクトの実際の状況に応じて選択して適用できます。個人的には、window.name メソッドは複雑ではなく、ほとんどすべてのブラウザーと互換性があり、非常に優れたクロスドメインメソッドだと思います。 。
上記は、JavaScript のクロスドメインの手法、原則、問題の解決策を紹介するこの記事の全内容です。皆様のお役に立てれば幸いです。