サーチ…
前書き
同一生成元ポリシーは、リモートアドレスがないスクリプトの同じ起源を持っている場合、リモート・コンテンツにアクセスできるようにするためのスクリプトを防ぐために、Webブラウザで使用されています。これにより、悪意のあるスクリプトが他のWebサイトに機密データを取得する要求を実行することを防止します。
両方のURLが同じプロトコル 、 ホスト名およびポートを持つ場合、2つのアドレスの起点は同じとみなされます 。
同じ出身政策を迂回する方法
クライアントサイドのJavaScriptエンジン(ブラウザ内で実行されるもの)に関しては、現在のドメイン以外のソースからコンテンツを要求するための直接的な解決策はありません。 (ところで、この制限はNode JSなどのJavaScriptサーバツールには存在しません)。
ただし、次の方法を使用して、他のソースからデータを取得することは実際には可能です(状況によっては)。ソリューション制作システムの代わりにハッキングや回避策を提示するものがあることに注意してください。
方法1:CORS
今日の公開APIのほとんどは、CORS(Cross-Origin Resource Sharing)と呼ばれる機能を有効にすることで、開発者がクライアントとサーバーの間で双方向にデータを送信できるようにします。ブラウザは、特定のHTTPヘッダー( Access-Control-Allow-Origin
)が設定されているかどうか、および要求元サイトのドメインがヘッダーの値にリストされているかどうかをチェックします。そうであれば、ブラウザはAJAX接続の確立を許可します。
ただし、開発者は他のサーバーの応答ヘッダーを変更できないため、この方法は必ずしも信頼できるものではありません。
方法2:JSONP
JSON with Pの追加は一般的に回避策になると非難されています。それは最も単純な方法ではありませんが、それでも仕事は終わります。この方法では、任意のドメインからスクリプトファイルをロードできるという利点があります。それでも、外部ソースからJavaScriptコードを要求することは常に潜在的なセキュリティ上のリスクであることに言及することは重要です。利用可能な解決策があれば、これは一般的に避けるべきです。
JSONPを使用して要求されたデータは、 JSONです 。これは、JavaScriptでオブジェクト定義に使用されている構文に合致しているため、この転送方法は非常に簡単です。 JSONPを介して取得した外部データをWebサイトに使用させる一般的な方法は、URLのGET
パラメータを介して設定されるコールバック関数内にラップすることです。外部スクリプトファイルがロードされると、関数のデータが最初のパラメータとして呼び出されます。
<script>
function myfunc(obj){
console.log(obj.example_field);
}
</script>
<script src="http://example.com/api/endpoint.js?callback=myfunc"></script>
http://example.com/api/endpoint.js?callback=myfunc
の内容は次のようになります。
myfunc({"example_field":true})
この関数は常に最初に定義する必要があります。そうでない場合は、外部スクリプトがロードされたときに定義されません。
メッセージとの安全なクロスオリジン通信
window.postMessage()
メソッドと相対イベントハンドラwindow.onmessage
を使用すると、クロスwindow.postMessage()
通信を有効にすることができます。
ターゲットwindow
のpostMessage()
メソッドは、別のwindow
にメッセージを送信するために呼び出すことができます。このメソッドは、そのonmessage
イベントハンドラでそれを傍受し、それを精緻化し、必要に応じて送信者ウィンドウに応答を返しますpostMessage()
もう一度実行します。
子フレームと通信するウィンドウの例
http://main-site.com/index.html
コンテンツ:<!-- ... --> <iframe id="frame-id" src="http://other-site.com/index.html"></iframe> <script src="main_site_script.js"></script> <!-- ... -->
http://other-site.com/index.html
コンテンツ:<!-- ... --> <script src="other_site_script.js"></src> <!-- ... -->
main_site_script.js
コンテンツ:// Get the <iframe>'s window var frameWindow = document.getElementById('frame-id').contentWindow; // Add a listener for a response window.addEventListener('message', function(evt) { // IMPORTANT: Check the origin of the data! if (event.origin.indexOf('http://other-site.com') == 0) { // Check the response console.log(evt.data); /* ... */ } }); // Send a message to the frame's window frameWindow.postMessage(/* any obj or var */, '*');
other_site_script.js
コンテンツ:window.addEventListener('message', function(evt) { // IMPORTANT: Check the origin of the data! if (event.origin.indexOf('http://main-site.com') == 0) { // Read and elaborate the received data console.log(evt.data); /* ... */ // Send a response back to the main window window.parent.postMessage(/* any obj or var */, '*'); } });