--- title: 同一オリジンポリシー slug: Web/Security/Same-origin_policy tags: - CORS - Host - JavaScript - Same-origin policy - Security - URL - origin - secure translation_of: Web/Security/Same-origin_policy ---
同一オリジンポリシーは重要なセキュリティの仕組みであり、ある{{Glossary("origin", "オリジン")}}によって読み込まれた文書やスクリプトが、他のオリジンにあるリソースにアクセスできる方法を制限するものです。制限するものです。
これにより、悪意のある可能性のあるドキュメントを隔離し、起こりうる攻撃のベクターを減らすことができます。例えば、インターネット上の悪意のあるウェブサイトがブラウザー内で JS を実行して、 (ユーザーがサインインしている) サードパーティのウェブメールサービスや (公開 IP アドレスを持たないことで攻撃者の直接アクセスから保護されている) 企業のイントラネットからデータを読み取り、そのデータを攻撃者に中継することを防ぎます。
二つのページの{{Glossary("protocol", "プロトコル")}}、{{Glossary("port", "ポート番号")}} (もしあれば)、{{Glossary("host", "ホスト")}}が等しい場合、両者のページは同じオリジンです。これは「スキーム/ホスト/ポート番号のタプル」または時に単に「タプル」として参照されます (「タプル」は共に全体を構成する三つの部分の組み合わせを表します)。
以下の表は、各行の URL が http://store.company.com/dir/page.html
と同じオリジンであるかを比較したものです。
URL | 結果 | 理由 |
---|---|---|
http://store.company.com/dir2/other.html |
同一オリジン | パスだけが異なる |
http://store.company.com/dir/inner/another.html |
同一オリジン | パスだけが異なる |
https://store.company.com/page.html |
不一致 | プロトコルが異なる |
http://store.company.com:81/dir/page.html |
不一致 | ポート番号が異なる (http:// は既定で80番ポート) |
http://news.company.com/dir/page.html |
不一致 | ホストが異なる |
about:blank
や javascript:
の URL のページから実行されたスクリプトは、その URL にオリジンのサーバーについての情報が明示的に含まれていないため、その URL を開いた文書のオリジンを継承します。
例えば、 about:blank
は (例えば {{domxref("Window.open()")}} メカニズムを使用して) 新しい空のポップアップウィンドウを生成し、その中に親スクリプトがコンテンツを書き込むために使用されます。ポップアップウィンドウにもコードが含まれた場合、そのコードはそれを生成したスクリプトと同じオリジンを継承します。
data:
の URL は新しく、空のセキュリティコンテキストを生成します。
Internet Explorer では、同一オリジンポリシーについて二つの大きな例外があります。
http://company.com:81/index.html
と http://company.com/index.html
は同一オリジンとみなされ、制限は適用されません。これらの例外事項は標準外であり、他のブラウザーはこのような挙動に対応していません。
ここで説明している ({{domxref("document.domain")}} セッターを使用する) 方法は非推奨です。同一オリジンポリシーによるセキュリティ保護を弱め、ブラウザーのオリジンモデルを複雑にして、相互運用性の問題やセキュリティバグを引き起こすためです。
ページのオリジンは、いくつかの制限の下で変更されることがあります。スクリプトを用いると、 {{domxref("document.domain")}} の値を現在のドメインまたは上位ドメインに変更できます。スクリプトによって現在のドメインの上位ドメインへオリジンが変更された場合、より短くなったドメイン名は次回のオリジン検査時に用いられます。
例えば、 http://store.company.com/dir/other.html
にあるドキュメント内のスクリプトが以下のコードを実行したと仮定します。
document.domain = "company.com";
このコードが実行された後、そのページは http://company.com/dir/page.html
におけるオリジンの検査を通過できます (許可を明示するために http://company.com/dir/page.html
が自身の document.domain
を "company.com
" に変更したと仮定します。詳しくは {{domxref("document.domain")}} を参照してください)。しかし、 company.com
が自身の
document.domain
を othercompany.com
に変更することはできません。なぜなら company.com
の上位ドメインではないためです。
ブラウザーはポート番号を個別に検査します。 document.domain
を呼び出すと、 document.domain = document.domain
の場合も含め、ポート番号が null
で上書きされます。従って、スクリプトの最初に document.domain = "company.com"
を設定しただけでは、 company.com:8080
と company.com
とは互いにアクセスできません。双方のポートが null
になるように、双方で設定しなければなりません。
この仕組みにはいくつかの制限があります。例えば、 document-domain
の Feature-Policy
が有効になっている場合や、文書がサンドボックス化された <iframe>
内にある場合は、 "SecurityError
" の DOMException
が発生します。また、この方法でオリジンを変更しても、多くの Web API (localStorage
, indexedDB
, BroadcastChannel
, SharedWorker
など) で使用されているオリジンチェックには影響しません。失敗事例のより詳細なリストは、 Document.domain > Failures にあります。
注: サブドメインから親ドメインへアクセスさせるために document.domain
を使用する際は、親ドメインとサブドメインの双方で同じ値を document.domain
に設定することが必要です。この作業は、親ドメインを元の値に戻す際にも必要です。これを怠ると権限エラーが発生します。
{{domxref("XMLHttpRequest")}} や {{htmlelement("img")}} 要素を使用する場合など、 同一オリジンポリシーは 2 つのオリジン間における通信を制御します。一般にこれらの通信は 3 つのカテゴリに分類されます。
以下に挙げるのは、異なるオリジンに埋め込むことができるリソースの例です。
<script src="..."></script>
で使用する場合。構文に関するエラーメッセージは、同一オリジンのスクリプトについてのみ読み取り可能です。<link rel="stylesheet" href="...">
で使用する場合。 CSS は緩い構文規則を持っているため、オリジンをまたぐ CSS には適切な Content-Type
ヘッダーを付加することが必要です。制約はブラウザーにより異なり、ブラウザーごとの詳細は Internet Explorer, Firefox, Chrome, Safari (日本語訳) (CVE-2010-0051 までスクロールしてください), Opera の各項目を参照してください。異なるオリジンへのアクセスを許可するには、 CORS を使用してください。 CORS は {{Glossary("HTTP")}} の一部で、ブラウザーがコンテンツの読み込みを許可する他のホストをサーバーが指定できるようにするものです。
Content-Type
を尊重しません。例えば <script>
タグで HTML 文書を指した場合、ブラウザーは HTML を JavaScript としてパースしようとします。リソースがサイトの入口ではない場合は、埋め込みを抑止するため CSRF トークンも使用するとよいでしょう。{{domxref("HTMLIFrameElement.contentWindow", "iframe.contentWindow")}}, {{domxref("window.parent")}}, {{domxref("window.open")}}, {{domxref("window.opener")}} といった JavaScript API を用いると、ドキュメントが直接互いに参照することができます。2 つのドキュメントが同一のオリジンではない場合、 {{domxref("Window")}} オブジェクトや {{domxref("Location")}} オブジェクトなど、限られたオブジェクトにのみアクセスすることができます。詳しくは次の 2 つのセクションで説明します。
{{domxref("window.postMessage")}} を使用すると、異なるオリジンの文書間における通信がさらに可能となります。
仕様書: HTML Living Standard § Cross-origin objects.
以下に示した Window
のプロパティは、異なるオリジンからのアクセスが許可されています。
メソッド |
---|
{{domxref("window.blur")}} |
{{domxref("window.close")}} |
{{domxref("window.focus")}} |
{{domxref("window.postMessage")}} |
属性 | |
---|---|
{{domxref("window.closed")}} | 読み取り専用 |
{{domxref("window.frames")}} | 読み取り専用 |
{{domxref("window.length")}} | 読み取り専用 |
{{domxref("window.location")}} | 読み取り/書き込み |
{{domxref("window.opener")}} | 読み取り専用 |
{{domxref("window.parent")}} | 読み取り専用 |
{{domxref("window.self")}} | 読み取り専用 |
{{domxref("window.top")}} | 読み取り専用 |
{{domxref("window.window")}} | 読み取り専用 |
一部のブラウザーでは、仕様書で定められたものより多くのプロパティでアクセスが許可されています。
以下に示した Location
のプロパティは、異なるオリジンからのアクセスが許可されています。
メソッド |
---|
{{domxref("location.replace")}} |
属性 | |
---|---|
{{domxref("URLUtils.href")}} | 書き込みのみ |
一部のブラウザーでは、仕様書で定められたものより多くのプロパティでアクセスが許可されています。
ウェブストレージや IndexedDB など、ブラウザー内部に保存されるデータへのアクセスは、オリジンによって権限が分かれています。それぞれのオリジンが個別にストレージを持ち、あるオリジンの JavaScript から別のオリジンに属するストレージを読み書きすることはできません。
{{glossary("Cookie", "Cookie")}} におけるオリジンの定義は異なります。ページは自身のドメインまたは任意の親ドメイン (親ドメインが public suffix ではない場合に限る) 用の Cookie を設定できます。 ドメインが public suffix であるかを判断する際、Firefox と Chrome は Public Suffix List を使用します。 Internet Explorer は独自の方法で public suffix であるかを判断します。使用しているスキーム (HTTP/HTTPS) やポートに関係なく、ブラウザーはサブドメインも含めて Cookie を使用可能にします。Cookie の設定時に Domain
, Path
, Secure
, HttpOnly
の各フラグを用いることで、その Cookie の利用範囲を制限できます。Cookie を読み取るとき、Cookie を設定した場所から知ることはできません。安全な https 接続のみ使用していたとしても、参照している Cookie は安全でない接続を通じて設定された可能性があります。