同一生成元ポリシー(Same-Origin Policy)

トップ > 同一生成元ポリシー(Same-Origin Policy)

同一生成元ポリシーとは

クロスサイトリクエストフォージェリ(CSRF)などのセキュリティ攻撃を防止するために、ブラウザは「同一生成元ポリシー(Same-Origin Policy)」という仕組みを実装しています。異なるオリジンのリソースへのアクセスに制約をかけるものです。制約はまた、JSONPCORS(Cross-Origin Resource Sharing) と呼ばれる仕組みを利用することで一部解除することができます。

オリジンとは

オリジン(Origin)は、スキーム、ホスト、ポート番号の組み合わせです。下記は同じオリジンとみなされます。

http://site-a.example.com/
http://site-a.example.com:80/
http://site-a.example.com/example.html

下記は異なるオリジンとみなされます。

https://site-a.example.com/      ← スキームが異なる
http://site-b.example.com/       ← ホストが異なる
http://site-a.example.com:8080/  ← ポート番号が異なる

ただし、Internet Explorer では、ポート番号のみが異なる場合は同じオリジンとみなします。

制約の例(XMLHttpRequest)

異なるオリジン(例えば site-a.example.com から site-b.example.com) に対する XMLHttpRequest や Fetch API を発行しても、その結果を responseText で読み出すことができません。呼び出せないのではなく、呼び出せてもその結果を取得できないことに注意してください。

HTML
<script>
window.addEventListener('load', function() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            console.log("status = " + xhr.status);  // status = 0
            console.log(xhr.responseText);          // Can not access
        }
    }
    xhr.open("POST", "http://site-b.example.com/");
    xhr.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    xhr.send("a=b&c=d");
});
</script>

この制約が発生すると、ブラウザのコンソールに下記の様なエラーメッセージが表示されます。

HTML
Access to XMLHttpRequest at 'http://site-b.example.com/' from origin 'http://site-a.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

site-b 側で Access-Control-Allow-Origin ヘッダを返却することにより、この制約を解除することができます。

制約の例(Canvas)

異なるオリジン(例えば site-a.example.com から site-b.example.com) の画像を Canvas に描画すると、Canvas は汚染された(tainted)とみなされ、canvas に対する toBlob(), toDataURL(), getImageData() などのアクセスが制限されます。

HTML
<script>
window.addEventListener('load', function() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.src = "http://site-b.example.com/img/test.png" + "?" + new Date().getTime();
    img.onload = function() {
        context.drawImage(img, 40, 40);
        var base64 = canvas.toDataURL("image/png");    // Error
        console.log(base64);
    }
});
</script>
<canvas id="canvas" width=100 height=100 style="border:1px solid gray;"></canvas>

この制約が発生すると、ブラウザのコンソールに下記の様なエラーメッセージが表示されます。

Error
Access to image at 'http://site-b.example.com/img/test.png' from origin 'http://site-a.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

site-b 側で Access-Control-Allow-Origin ヘッダを返却し、イメージに crossorigin を設定することにより、この制約を解除することができます。

HTML
    var img = new Image();
    img.crossOrigin = "anonymous";
    img.src = "http://site-b.example.com/img/test.png" + "?" + new Date().getTime();

制約の例(Iframe)

異なるオリジン(例えば site-a.example.com から site-b.example.com) のコンテンツを iframe に表示した場合、そのフレームに対する contentWindow アクセスが制限されます。

HTML
<script>
window.addEventListener('load', function() {
    var iframe = document.getElementById("iframe");
    var doc = iframe.contentWindow.document;    // Error
    console.log(doc);
});
</script>
<iframe src="http://site-b.example.com/" id="iframe"<>/iframe>

この制約が発生すると、ブラウザのコンソールに下記の様なエラーメッセージが表示されます。

Error
Uncaught DOMException: Blocked a frame with origin "http://site-a.example.com" from accessing a cross-origin frame.

この制約は解除することができないようです。

その他の制約

上記の他にも @font-face による外部フォントアクセス、WebGL によるアクセス、スクリプトに対する onerror による詳細エラー情報取得などに制約があるようです。制約の条件や範囲はブラウザの実装により異なります。

Access-Control-Allow-Origin ヘッダ

異なるオリジン間の制限を解除するために、Origin や Access-Control-Allow-Origin ヘッダを使用します。site-a.example.com から、site-b.example.com のリソースにアクセスする際、XMLHttpRequest や、crossorigin="anonymous" が指定された <img>, <script>, <audio>, <video>, <link> では、クライアントからサーバに対して下記の HTTP ヘッダが送信されます。

HTTP Header
Origin: http://site-a.example.com

これに対し、サーバから下記のヘッダが返却されると、ブラウザは、他のオリジンからのアクセスを許可されたリソースであると判断し、XMLHttpRequest や Canvas などの制約を解除します。

HTTP Header
Access-Control-Allow-Origin: *

特定のサイトにのみ制限を解除する場合は、下記の様に許可する対象のオリジンを返却します。

HTTP Header
Access-Control-Allow-Origin: http://site-a.example.com

Copyright (C) 2018 杜甫々
初版:2018年12月29日 最終更新:2018年12月29日
http://www.tohoho-web.com/ex/same-origin-policy.html