同一生成元ポリシーによって、ある生成元から読み込まれた文書やスクリプトが、異なる生成元からの文書のプロパティを取得したり設定したりするのを防ぎます。
生成元の定義
もしプロトコル、(与えられていれば) ポート、及びホストが両方のページで同じならば、Mozilla は二つのページが同一生成元を持っていると見なします。説明するために、以下の表では URL https://store.company.com/dir/page.html
との生成元の比較の例を挙げています。
URL | 結果 | 理由 |
---|---|---|
https://store.company.com/dir2/other.html |
成功 | |
https://store.company.com/dir/inner/another.html |
成功 | |
https://store.company.com/secure.html |
失敗 | 異なるプロトコル |
https://store.company.com:81/dir/etc.html |
失敗 | 異なるポート |
https://news.company.com/dir/other.html |
失敗 | 異なるホスト |
file:
URL の生成元の定義もご覧ください。
Cookie は生成元の定義に使用しますが、上記とは異なります。
生成元の変更
ページの生成元は、いくつかの制限のもとに変更することができます。スクリプトは {{domxref("document.domain")}} の値を現在のドメインのサフィックスに設定できます。もしスクリプトによってそのように設定されたら、より短いドメインは次の生成元のチェックのために使われます。例えば、https://store.company.com/dir/other.html
にある文書内のスクリプトが以下の命令文を実行したと想定します:
document.domain = "company.com";
この命令文の実行後、ページは https://company.com/dir/page.html
で生成元のチェックを通るでしょう。しかし、同じ理由で、company.com
は document.domain
を othercompany.com
に設定することはできません。
ポート番号はブラウザにより、別に保持されます。document.domain = document.domain
を含むどのような設定の呼び出しでも、ポート番号は null
で上書きされます。従って始めに document.domain = "company.com"
を設定しただけでは、company.com:8080
と company.com
が交流することはできません。双方のポート番号が null
になるように、双方で設定しなければなりません。
注記: サブドメインが親ドメインへ安全にアクセスできるようにするために document.domain
を使用するときは、親ドメインとサブドメインの双方で document.domain
に同じ値を設定することが必要です。これは、単に親ドメインを元の値に戻す設定を行う場合でも必要です。これを怠るとパーミッションエラーが発生するでしょう。
異なる生成元へのネットワークアクセス
同一生成元ポリシーは {{domxref("XMLHttpRequest")}} を使用する場合など、2 つの生成元間の対話を制御します。これらの対話は一般的に、3 つのカテゴリに分けられます:
- 異なる生成元への書き込みは、概して許可されます。例えばリンク、リダイレクトやフォームの送信です。まれに使用される HTTP リクエストでは、プリフライトが必要です。
- 異なる生成元の埋め込みは、概して許可されます。例は後述します。
- 異なる生成元からの読み込みは概して許可されませんが、埋め込みによって読み込みアクセスはしばしば漏れ出します。例えば埋め込み画像の幅や高さ、埋め込みスクリプトのアクション、あるいは埋め込みリソースで可能なものを読み取ることが可能です。
以下に、異なる生成元で埋め込むことが可能なリソースの例を挙げます:
<script src="..."></script>
による JavaScript。構文エラーのエラーメッセージは、同一生成元のスクリプトについてのみ利用可能です。<link rel="stylesheet" href="...">
による CSS。CSS の寛大な構文規則のため、生成元を越える CSS は適切なContent-Type
ヘッダが必要です。制約はブラウザにより異なります: IE (日本語訳)、Firefox (日本語訳)、Chrome、Safari (日本語訳) (CVE-2010-0051 までスクロールしてください)、Opera。- {{htmlelement("img")}} による画像。サポートされる画像形式は PNG、JPEG、GIF、BMP、SVG などです。
- {{htmlelement("video")}} および {{htmlelement("audio")}} によるメディアファイル。
<object>
、<embed>
および<applet>
によるプラグイン。@font-face
によるフォント。異なる生成元のフォントを許可するブラウザもありますが、同一生成元のフォントを要求するブラウザもあります。<frame>
および<iframe>
によるものは何でも。このような方式による異なる生成元との対話を防ぐために、サイトでX-Frame-Options
ヘッダを使用できます。
異なる生成元とのアクセスを許可する方法
異なる生成元とのアクセスを許可するには、CORS を使用します。
異なる生成元とのアクセスをブロックする方法
- 異なる生成元への書き込みを防ぐには、リクエスト内の推測できないトークン (Cross-Site Request Forgery (CSRF) トークンとして知られる) をチェックして、このトークンを知っているページの、異なる生成元からの読み込みを止めます。
- 異なる生成元のリソースの読み込みを防ぐには、そのリソースを埋め込みできないようにします。
- 異なる生成元からの埋め込みを防ぐには、リソースが前出の埋め込み可能な形式であると判断されないようにしてください。ほとんどの場合、ブラウザは
Content-Type
を尊重しません。例えば<script>
タグで HTML ドキュメントを指した場合、ブラウザは HTML を JavaScript としてパースしようとします。リソースがサイトの入り口ではない場合は、CSRF トークンも使用するとよいでしょう。
異なる生成元へのスクリプトアクセス
iframe.contentWindow
、{{domxref("window.parent")}}、{{domxref("window.open")}}、{{domxref("window.opener")}} といった JavaScript API は、ドキュメントが互いに直接参照することを可能にします。2 つのドキュメントが同一の生成元ではないとき、これらの参照は Window オブジェクトや Location オブジェクトへの限られたアクセスを提供します。一部のブラウザは、仕様が許可するものより多くのプロパティへのアクセスを許可します。ドキュメント間で通信する代わりに、{{domxref("window.postMessage")}} を使用することができます。
関連情報
Original Document Information
- Author(s): Jesse Ruderman