CORS

概要

現在の Web ブラウザーでは、1 つの Web サイトが持つ情報が別の悪意ある Web サイトに悪用されることを防ぐため、Same-Origin Policy(同一オリジンポリシー)が適用される。

たとえば、異なるドメインのバックエンド API とフロントエンド間で通信してリソースを要求すると、Origin(ドメイン、プロトコル、ポート番号)が異なるためエラーが発生する。https://api.devkuma.com/ の Web ページから XHR や Fetch API で https://www.devkuma.com/ のデータを HTTP(S) で読み込もうとするとエラーになる。

しかし、信頼関係のある Web サイトまで制限してしまうと不便であるため、データアクセスを許可できる Web サイトについては Origin が異なってもアクセスできるようにする CORS(Cross-Origin Resource Sharing)が必要になる。

CORS とは?

  • Cross-Origin Resource Sharing の略で、オリジン間のリソース共有を意味する。
  • ブラウザーは異なるオリジン間の通信を原則として禁止しているが、CORS 設定により別オリジン間でも通信できる。
  • ブラウザーで見ているページとは別のドメインからデータを受け取ることを許可する方式である。
  • セキュリティ上、クロスサイトスクリプティングを防ぐために使用される。

Origin(オリジン)とは?

Web コンテンツの Origin は、そのコンテンツへアクセスするために使われる URL のスキーム(プロトコル)、ホスト(ドメイン)、ポートによって定義される。スキーム、ホスト、ポートがすべて一致する場合にのみ、2 つは同じ Origin と言える。

同一 Origin の例

http://www.devkuma.com/app1/index.html
http://www.devkuma.com/app2/index.html

異なる Origin の例

http://devkuma.com/app1
https://devkuma.com/app2
http://devkuma.com
http://www.devkuma.com
http://www.devkuma.com
http://www.devkuma.com:8080

なぜ CORS が必要なのか?

ブラウザーはセキュリティ上の理由で同一オリジンポリシーを採用している。他の出所から自分のリソースに勝手にアクセスできないようにするためである。

もし自分がサービスしていないサイトからセッションのリクエストを取得できるなら、そのサイトはセッションを奪取して悪用する可能性がある。ブラウザーはこのようなリクエストを防いでいる。

CORS はどのように動作するか

ブラウザーがリソースを要求するとき、追加ヘッダーに Origin、使用するメソッド、含めるヘッダー情報を入れてサーバーへ送信する。サーバーは応答可能な Origin をヘッダーに入れてブラウザーへ返す。ブラウザーはこのヘッダーを確認し、その Origin から要求できるならリソース転送を許可し、不可能ならエラーを発生させる。

CORS preflight リクエスト

HTTP ヘッダーの送受信で構成される仕組みであり、ブラウザーがオリジンを越えた要求への応答にフロントエンド JavaScript コードがアクセスできるかどうかを決定する。

Request Header 一覧

  • Origin: どの Origin からアクセスしているかを示す。
  • Access-Control-Request-Method: preflight リクエスト時に、実際のリクエストで使用するメソッドをサーバーに知らせる。
  • Access-Control-Request-Headers: preflight リクエスト時に、実際のリクエストで使用するヘッダーをサーバーに知らせる。

Response Header 一覧

  • Access-Control-Allow-Origin: ブラウザーが該当 Origin からリソースへアクセスできるよう許可する。
  • Access-Control-Expose-Headers: 応答の一部として公開してよいヘッダーを示す。
  • Access-Control-Max-Age: preflight リクエスト結果をキャッシュできる時間を示す。
  • Access-Control-Allow-Credentials: credentials が true のとき、リクエストへの応答を公開できるかを示す。
  • Access-Control-Allow-Methods: preflight リクエストへの応答として許可されるメソッドを示す。
  • Access-Control-Allow-Headers: 実際のリクエストで使用できる HTTP ヘッダーを示す。

CORS 使用例

https://api.devkuma.com に対して、別 Web サイト https://www.devkuma.com からの HTTP(S) アクセスを許可する場合を例に説明する。

単純に GET と POST を許可するには、サーバーが HTTP レスポンスヘッダーに次を追加する。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com

Cookie を許可する場合は、ブラウザーとサーバーの両方で設定が必要である。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Credentials: true

GET、POST、HEAD 以外のメソッドやカスタムヘッダーを使う場合は、実際の HTTP リクエスト前に OPTIONS の preflight request が行われる。

参照