同一オリジンポリシー / CORS
同一オリジンポリシー(Same origin policy)と、その制限を回避する機能であるCORS(Cross-Origin Resource Sharing)についてのまとめです。
同一オリジンポリシーについてオリジンとは同一オリジンポリシーとは同一オリジンポリシーが必要な理由同一オリジンポリシーの適用対象同一オリジンポリシーによって制限を受けるもの同一オリジンポリシーによって制限を受けないものCORSについて(同一オリジンポリシーの回避)CORSとは通信フローシンプルリクエストの場合の通信フロープリフライトリクエストの場合の通信フローCORSに関連するHTTPヘッダ一覧
同一オリジンポリシーについて
オリジンとは
まず、オリジン(Origin)とは、URL内の「スキーム(プロトコル)+FQDN(ホスト+ドメイン)+ポート番号」の組み合わせのこと。
英語「Origin」を和訳すると「出所」や「起源」という意味になり、コンテンツの送信元のことを表す。
以下の場合、ポート番号の表記は省略される
・スキームが「http」でポート番号が「80」
・スキームが「https」でポート番号が「443」
同一オリジンポリシーとは
同一オリジンポリシー(Same-Origin Policy: SOP)とは、あるオリジンから取得したリソースから、別のオリジンのリソースへのアクセスを禁止するブラウザの機能のこと。
「同一生成元ポリシー」や「同一源泉ポリシー」とも表記される。
【例】 オリジン「https://aaa.com」から取得したリソースaが、追加でリソースAとリソースBを取得する場面において、同一オリジンポリシーが適用された結果を下記の図に示す。
- リソースA:リソースaと同一のオリジン「https://aaa.com」から取得するので成功!
- リソースB:リソースaと異なるオリジン「https://bbb.com」から取得するので失敗。
同一オリジンポリシーが必要な理由
- クロスサイトスクリプティング(XSS)やクロスサイトリクエストフォージェリ(CSRF)等のサイバー攻撃を防ぐため。
- ログイン後のみ表示される情報を他のサイトから参照されることを防ぐため。
同一オリジンポリシーの適用対象
同一オリジンポリシーが適用される対象(読み込みなどで制限受ける対象)および、適用されない対象(制限を受けない対象)についてまとめてみた。
同一オリジンポリシーによって制限を受けるもの
異なるオリジンからのリソースの読み込みは一般的に禁止される。(同一オリジンポリシーの適用対象)
- JavaScriptでの非同期通信(XMLHttpRequestやFetch APIを使った通信)
- Canvas
- Web Storage
- JavaScriptでの画像データの読み込み
同一オリジンポリシーによって制限を受けないもの
異なるオリジンへのアクセス・書き込みや、異なるオリジンのリソースの埋め込みは許可される。(同一オリジンポリシーの適用対象外)
- タグ内の属性で読み込まれるJavaScript
- タグ内の属性で読み込まれるCSS
- タグ内の属性で埋め込まれる画像
- , タグ内の属性で埋め込まれるメディアファイル
- , で指定されたリソース
- , , タグによるプラグイン
- , タグ内の属性での別サイトコンテンツの読み込み
- タグ内の属性で指定した情報送信先
CORSについて(同一オリジンポリシーの回避)
CORSとは
CORS(Cross-Origin Resource Sharing)とは、同一オリジンポリシーの制限を回避する際に利用する機能。異なるオリジンのサーバからのアクセスを許可できる仕組み。
異なるオリジンからのリソースを読み込もうとした場合、ブラウザは以下のようなエラーをコンソールに出力し、読み込みを禁止する。
異なるオリジンのサーバからのアクセスを許可したい場合、レスポンス内の「Access-Control-Allow-Origin」と呼ばれるHTTPヘッダの値に、許可したいサーバのオリジン情報を設定しておくことで正常なアクセスが可能となる。
通信フロー
CORSによって異なるオリジンからのリソースの読み込みを許可する場合の通信フローを示す。
HTTPリクエストの種別( or )によって通信フローは異なる。
シンプルリクエストとは
通信によりサーバのデータが変化しないHTTPリクエスト。
具体的には下記の条件を満たすHTTPリクエスト。
- メソッドが or or
- HTTPヘッダが下記以外のものは含まない
, , , , , , , ,
- Content-Typeが or or
プリフライトリクエストとは
シンプルリクエストの条件を満たさず、通信によりサーバのデータが変化する恐れのあるHTTPリクエスト。
実際のリクエストの前にメソッドによって通信し、実際のリクエストを送っても問題ないかを確認する工程がある。
シンプルリクエストの場合の通信フロー
① クライアントは https://aaa.com へアクセス。
② サーバ aaa.com はレスポンスを返す。
③ ブラウザは追加コンテンツを取得するため、https://bbb.com へアクセス。
Originヘッダにて、呼び出し元のオリジン(https://aaa.com/)を指定する。
④ サーバ bbb.com はAccess-Control-Allow-Originヘッダに表示を許可する呼び出し元として https://aaa.com/ を指定し、コンテンツを送信。
プリフライトリクエストの場合の通信フロー
異なるオリジンへの通信の際、始めに OPTIONS メソッドで対象の異なるオリジンにリクエストを送り、実際のリクエストを送っても問題ないかを確認する。
① クライアントは https://aaa.com へアクセス。
② aaa.com のサーバはレスポンスを返す。
③ ブラウザは https://bbb.com へリクエスト送信して問題ないかを確認。(呼び出し元ドメインや送信予定のリクエストのメソッド・ヘッダ情報を送信)
④ サーバ bbb.com は③の条件のリクエストを受け入れOKの場合、受け入れ可能条件を送信。
⑤ ブラウザは追加コンテンツ取得のため、https://bbb.com へアクセス。
⑥ サーバ bbb.com はAccess-Control-Allow-Originヘッダに表示を許可する呼び出し元として https://aaa.com/ を指定し、コンテンツを送信。