web-dev-qa-db-ja.com

同一オリジンポリシーを回避する方法

同じOriginポリシー

私はHTML/JSsame-Originポリシーに関するコミュニティウィキを作り、このトピックを探している人を助けたいと願っています。これはSOで最も検索されているトピックの1つであり、統合されたWikiはありませんので、ここに行きます:)

同じOriginポリシーは、あるOriginからロードされたドキュメントまたはスクリプトが別のOriginからドキュメントのプロパティを取得または設定することを防ぎます。この方針は、Netscape Navigator 2.0までさかのぼります。

同一オリジンポリシーを回避するための最も好きな方法は何ですか?

例を冗長にし、できればあなたの情報源もリンクしてください。

150
David Titarenco

document.domainメソッド

  • メソッドの種類:iframe

これは、document.domainの値を現在のドメインのサフィックスに設定するiframeメソッドです。もしそうであれば、より短いドメインがその後のOriginチェックに使われます。たとえば、ドキュメントのhttp://store.company.com/dir/other.htmlにあるスクリプトが次の文を実行するとします。

document.domain = "company.com";

そのステートメントが実行された後、ページはhttp://company.com/dir/page.htmlでOriginチェックに合格します。しかし、同じ理由で、company.comはdocument.domainothercompany.comに設定できませんでした。

この方法では、メインドメインにあるページのサブドメインにあるiframeからjavascriptを実行することができます。 Firefoxのようなブラウザではdocument.domainを完全に別名のドメインに変更することはできないため、この方法はクロスドメインリソースには適していません。

出典: https://developer.mozilla.org/ja/Same_Origin_policy_for_JavaScript

クロスオリジンリソース共有方式

  • メソッドの種類:AJAX

クロスオリジンリソース共有 (CORS)は、起点を越えてソースにアクセスするときにブラウザとサーバーが通信する方法を定義するW3Cワーキングドラフトです。 CORSの背後にある基本的な考え方は、要求と応答が成功するか失敗するかを判断するためにブラウザとサーバーの両方が互いについて十分に知ることができるようにカスタムHTTPヘッダーを使用することです。

単純なリクエストの場合、カスタムヘッダなしでGETまたはPOSTを使用し、本文がtext/plainの場合、リクエストはOriginという追加のヘッダとともに送信されます。 Originヘッダーには、リクエストしているページのオリジン(プロトコル、ドメイン名、およびポート)が含まれているため、サーバーはレスポンスを提供する必要があるかどうかを簡単に判断できます。 Originヘッダーの例は次のようになります。

Origin: http://www.stackoverflow.com

リクエストを許可するとサーバーが判断した場合は、送信されたのと同じOriginをエコーバックするAccess-Control-Allow-Originヘッダーを送信します。パブリックリソースの場合は*を送信します。例えば:

Access-Control-Allow-Origin: http://www.stackoverflow.com

このヘッダが見つからない場合、または元が一致しない場合、ブラウザはリクエストを許可しません。すべて問題なければ、ブラウザはリクエストを処理します。リクエストもレスポンスもクッキー情報を含まないことに注意してください。

Mozillaチームは、 でCORS についての投稿で、ブラウザがXHRによるCORSをサポートしているかどうかを判断するためにwithCredentialsプロパティの存在をチェックするべきであると提案します。その後、すべてのブラウザをカバーするためにXDomainRequestオブジェクトの存在と組み合わせることができます。

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
    request.onload = function() {
        // ...
    };
    request.onreadystatechange = handler;
    request.send();
}

CORSメソッドを機能させるには、あらゆる種類のサーバーヘッダーメカニズムにアクセスする必要があり、単にサードパーティのリソースにアクセスすることはできません。

出典: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-Origin-resource-sharing/

window.postMessageメソッド

  • メソッドの種類:iframe

window.postMessageを呼び出すと、実行する必要がある保留中のスクリプトが完了したときにMessageEventがターゲットウィンドウに送出されます(たとえば、window.postMessageがイベントハンドラから呼び出された場合は残りのイベントハンドラ、以前に設定した保留タイムアウトなど)。 MessageEventは型メッセージ、window.postMessageに与えられた最初の引数の文字列値に設定されるdataプロパティ、window.postMessageが呼び出された時点でwindow.postMessageを呼び出すウィンドウ内のメイン文書の原点に対応するOriginプロパティ、そしてwindow.postMessageが呼び出されるウィンドウであるsourceプロパティ。

window.postMessageを使用するには、イベントリスナを添付する必要があります。

    // Internet Explorer
    window.attachEvent('onmessage',receiveMessage);

    // Opera/Mozilla/Webkit
    window.addEventListener("message", receiveMessage, false);

そしてreceiveMessage関数は宣言されなければなりません:

function receiveMessage(event)
{
    // do something with event.data;
}

オフサイトのiframeもpostMessageを介してイベントを正しく送信する必要があります。

<script>window.parent.postMessage('foo','*')</script>

ウィンドウ内のドキュメントの場所に関係なく、メッセージを送信するために、どのウィンドウでも他のウィンドウのこのメソッドにアクセスできます。したがって、メッセージを受信するために使用されるイベントリスナーは、Originおよび場合によってはソースプロパティを使用して、メッセージの送信者の身元を最初に確認する必要があります。これは控えめに言うことはできません。Originおよび場合によってはsourceプロパティをチェックしないと、クロスサイトスクリプティング攻撃が可能になります。

出典: https://developer.mozilla.org/ja/DOM/window.postMessage

84
David Titarenco

リバースプロキシ方式

  • メソッドの種類:Ajax

サーバー上で単純な リバースプロキシ を設定すると、ブラウザはAjaxリクエストに相対パスを使用できますが、サーバーはプロキシとして機能します。任意の遠隔地に。

Apacheで mod_proxy を使用する場合、リバースプロキシを設定するための基本的な設定ディレクティブはProxyPassです。通常は次のように使用されます。

ProxyPass     /ajax/     http://other-domain.com/ajax/

この場合、ブラウザは相対URLとして/ajax/web_service.xmlを要求できますが、サーバーはhttp://other-domain.com/ajax/web_service.xmlへのプロキシとして機能することによってこれを提供します。

この方法の興味深い特徴の1つは、リバースプロキシが複数のバックエンドに要求を簡単に分散できることです。したがって、 ロードバランサー として機能します。

41
Daniel Vassallo

私はJSONPを使います。

基本的には、あなたが追加

<script src="http://..../someData.js?callback=some_func"/>

あなたのページに。

データが入っていることが通知されるようにsome_func()が呼び出されるはずです。

17
Nicolas Viennot

AnyOriginはいくつかのhttpsサイトでうまく機能しなかったので、私はちょうどhttpsでうまくいくように思われる whateverorigin.org と呼ばれるオープンソースの代替案を書いた。

githubのコード

13
ripper234

私はこの画像の信用を主張することはできませんが、それはこの主題について私が知っているすべてのものと一致し、同時に少しユーモアを提供します。

http://www.flickr.com/photos/iluvrhinestones/5889370258/

12
Mat Schaffer

私が見つけた同じOriginのポリシーを克服するための最新の方法は http://anyorigin.com/ です。

このサイトでは、URLを指定するだけでjavascript/jqueryコードが生成されるので、Originの種類に関係なくHTML/dataを取得できます。つまり、URLやWebページをJSONPリクエストにします。

私はそれがかなり便利だと思いました:)

これがanyoriginからのJavaScriptコードの例です。

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});
12
rk1s

JSONP が頭に浮かぶ:

JSONPまたは「パディング付きJSON」は、基本のJSONデータ形式、つまりページがプライマリサーバー以外のサーバーから要求してより有意義にJSONを使用できるようにする使用パターンを補完するものです。 JSONPは、クロスオリジンリソース共有と呼ばれるより最近の方法に代わるものです。

3
Sarfraz

さて、私はこれを回避するためにPHPでcurlを使用しました。ポート82でWebサービスを実行しています。

<?php

$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;

?>

これはPHPファイルを呼び出すJavaScriptです。

function getdata(obj1, obj2) {

    var xmlhttp;

    if (window.XMLHttpRequest)
            xmlhttp=new XMLHttpRequest();
    else
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
                document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
    }
    xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
    xmlhttp.send();
}

私のHTMLはWAMPの80番ポートで動作します。そこで、同じOriginポリシーを回避しました:-)

1
harihb

これはほぼそこで利用可能なものを分析します。 http://www.slideshare.net/SlexAxton/breaking-the-cross-domain-barrier

PostMessageソリューションのために見てみる:

https://github.com/chrissrogers/jquery-postmessage/blob/master/jquery.ba-postmessage.js

そしてわずかに異なるバージョン:

https://github.com/thomassturm/ender-postmessage/blob/master/ender-postmessage.js

1
Chris Cinelli

個人的には、window.postMessageは私が最近のブラウザで見つけた最も信頼できる方法です。 XSS攻撃にさらされないようにするには、もう少し作業を増やす必要がありますが、これは妥当なトレードオフです。

上記の他の方法を使用して古いブラウザと同様の機能を提供する、window.postMessageをラップする人気の高いJavascriptツールキット用のプラグインもいくつかあります。

1
Justin Niessner

同じオリジンポリシーのいくつかの回避策および説明はここにあります:
Thiru's Blog - ブラウザと同じOriginポリシーの回避策

1
Thiru