はじめに
CORS(Cross-OriginResourceSharing)メモ
参考
流れ
CORS(Cross-Origin Resource Sharing)は、ウェブページが別のドメインから取得したリソースにアクセスできるようにブラウザで実装されているセキュリティ機能です。その仕組みは主にブラウザ側に実装されています。
CORSの基本的な流れ
-
ブラウザによる判断
- ブラウザは、あるオリジン(ドメイン、プロトコル、ポートが組み合わさったもの)からロードされたウェブページが別のオリジンのリソースにアクセスしようとすると、CORSポリシーを適用します。(クロスオリジン)
シンプルなGETやPOSTのような安全なリクエストの場合、ブラウザは通常のHTTPリクエストにOriginヘッダを付加してサーバーに送信します。(同一オリジンポリシー)
- ブラウザは、あるオリジン(ドメイン、プロトコル、ポートが組み合わさったもの)からロードされたウェブページが別のオリジンのリソースにアクセスしようとすると、CORSポリシーを適用します。(クロスオリジン)
-
プリフライトリクエスト
- 特定の条件(非標準のHTTPヘッダを使用する、またはHTTPメソッドなどが特定の種類である場合など)に該当するリクエストを行う際、ブラウザはまず「プリフライトリクエスト」と呼ばれる事前確認を送ります。
これは、本来のリクエストを送信する前に、OPTIONSメソッドを使用してサーバーに対し、本来のリクエストを安全に受け入れることが可能かどうかを問い合わせるものです。
- 特定の条件(非標準のHTTPヘッダを使用する、またはHTTPメソッドなどが特定の種類である場合など)に該当するリクエストを行う際、ブラウザはまず「プリフライトリクエスト」と呼ばれる事前確認を送ります。
-
サーバーの応答
- サーバーは、Access-Control-Allow-OriginのようなCORSに関連するヘッダをレスポンスに含めて、リクエストが受け入れられるか、どのオリジンからのリクエストが許可されるかをブラウザに指示します。
ブラウザによるリソースの読み込み:
- サーバーは、Access-Control-Allow-OriginのようなCORSに関連するヘッダをレスポンスに含めて、リクエストが受け入れられるか、どのオリジンからのリクエストが許可されるかをブラウザに指示します。
ブラウザはサーバーからのレスポンスを確認し、CORSポリシーに基づいてリクエストが許可されている場合は、アプリケーションにリソースを読み込むことを許可します。そうでない場合は、アクセスをブロックします。
同一オリジンポリシー
同一オリジンからの情報読み出しは可能だが、クロスオリジン(同一オリジンではない)からの読み出しは基本できない。同一オリジンの定義は下記参照。
クロスオリジンからの読み出し
シンプルなリクエストの場合はAccess-Control-Allow-Origin: 読み出したいサーバの FQDN
がサーバ(情報提供側)のレスポンスに含まれていると、クロスオリジンの情報を読み取ることができる。
例えばReactサーバとAPIサーバと別れていたら、APIサーバのレスポンスのAccess-Control-Allow-Origin
にはReaxtサーバのFQDNを指定しないといけない
シンプルなリクエストとは
以下参照
プリフライトリクエスト
- シンプルなリクエストの条件を満たさない場合、ブラウザはプリフライトリクエストというHTTPリクエストを送信する(外部へのアクセス前に)。これにより、ブラウザはサーバーからのレスポンスを確認し、実際のリクエストを安全に送信できるかどうかを判断します。
シンプルなリクエストの条件を満たさない場合のクロスオリジンの情報を読み出す方法
プリフライトリクエストを正常に通過させ、クロスオリジンの情報を読み出すためには、サーバー側(情報提供側)で以下の設定を行う必要があります
-
Access-Control-Allow-Origin:
- このヘッダーで、どのオリジンからのリクエストを許可するかを指定します。
-
Access-Control-Allow-Methods:
- どのHTTPメソッドを許可するかを指定します。例:POST, GET, PUT など。
-
Access-Control-Allow-Headers:
- リクエストで許可されるヘッダーを指定します。特にカスタムヘッダーや、特定の認証に関連するヘッダーなど、シンプルなリクエストの条件にないヘッダーを使う場合は、ここで明示的に許可する必要があります。
上記3つは基本的に必須
- Access-Control-Max-Age: このヘッダーを使用して、ブラウザがプリフライトレスポンスをキャッシュする時間(秒単位)を指定できます。これにより、同じリクエストを繰り返し送る際のオーバーヘッドを削減できます。レスポンスしたほうが便利。
サーバー側でこれらのヘッダーを適切に設定することで、シンプルなリクエストの条件を満たさないクロスオリジンのリクエストでも、情報を正常に読み出すことができます。
認証情報を含むリクエスト
- デフォルトでクロスオリジンに対するリクエストにはクッキーなどの認証用に伴う情報はリクエストヘッダには自動的に送信されない。
- 認証用のヘッダを送信するようにするには
- クライアント側ではXMLHttpRequestのプロパティwithCredentialsをtrueにセットする必要がある。
- APIサーバ側(情報提供側)では
Access-Control-Allow-Credentails:true
を返す必要がある。