2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CORSを理解する

2
Posted at

CORSとは

CORSとは、追加のHTTPヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンに選択されたリソースへのアクセス権を与えるようブラウザに指示するための仕組みのことで、オリジン間リソース共有と呼ばれています。

オリジンって何?

オリジンとは、ウェブコンテンツにアクセスするために使われるURLの スキーム(プロトコル)ホスト(ドメイン)ポートによって定義されているものです。

例えば、http://example.jpの場合

  • スキーム : http
  • ホスト : example.jp
  • ポート : 80 (httpのデフォルト値)

同一オリジンポリシーとは

ではなぜCORSは必要なのか、それを理解するためには同一オリジンポリシーの理解が必要です。

同一オリジンポリシーとは、重要なセキュリティーの仕組みであり、あるオリジンによって読み込まれた文書やスクリプトが、他のオリジンにあるリソースにアクセスできる方法を制限するものです。セキュリティにおける重要な仕組みであり、悪意ある行動を起こしかねないリソースの分離を目的としています。

この仕組みによって、webページを生成したオリジン以外へのHTTPリクエストはできなくなります。

もし同一オリジンポリシーがなかったらどうなるか

  1. 悪意ある人から届いたメールにリンクが貼ってある
  2. そのリンクをクリックすることで遷移し、JSがダウンロードされ実行される
  3. 攻撃対象のサイトへリクエストが送られる
  4. そのサイトの個人情報などが悪意あるサイトへ送られる(個人情報漏洩)

同一オリジンポリシーがある場合

攻撃対象であるサイトへリクエストを行った時点でブロックされるので情報漏洩を避けることができます。

同一オリジンポリシーのおかげで、別のオリジンであるサイトへのリクエストは通らなくなります。

おかげで悪意ある攻撃から情報などを守ることができるようになったのですが、異なるオリジンへのアクセスはできなくなりました。

しかし、AJAXの普及によりAPI呼び出しなどで異なるオリジンへのアクセスが必要になりました。
そこで発案されたのがCORSです。

CORSの基本特性

提供する機能

  • クロスオリジンのリソースアクセスを提供
  • オリジン単位のアクセス制御を提供

後方互換性

  • 従来動作しているサイトもCORSの元でも動作する
  • 従来のCORSを使用しないサイトの性能劣化は無視できる程小さい
  • 従来セキュリティ上問題のないサイトがCORSの元でも安全に動作する

HTTPヘッダを用いたアクセス制御

  • リクエストヘッダ : Origin, Access-Control-Request-XXXX
  • レスポンスヘッダ : Access-Control-Allow-XXXX

リクエスト

  • 単純リクエストについては無条件でリクエストを送信して、レスポンスヘッダにより、JavaScriptがリソースを受け取れるか否かを判断
  • 単純ではないリクエストに関しては、プリフライトリクエストにより、リクエスト送信の許可を得る

CORS対応ブラウザの挙動

許可がない場合

  1. http://example.jpへアクセスしJSファイルをダウンロード
  2. JSからGETでAPIを提供するhttp://api.example.netへリクエストを行う
  3. リクエストを行うにはリクエストヘッダにOriginを付与したリクエストを行う
    Origin: http://example.jp
  4. APIサーバーがJSONを作り、レスポンスを返す
  5. レスポンスヘッダにAccess-Control-Allow-Originがないためレスポンスを受け取ることはできない
    image.png

許可がある場合

  1. http://example.jpへアクセスしJSファイルをダウンロード
  2. JSからGETでAPIを提供するhttp://api.example.netへリクエストを行う
  3. リクエストを行うにはリクエストヘッダにOriginを付与したリクエストを行う
    Origin: http://example.jp
  4. APIサーバーがJSONを作り、レスポンスを返す
  5. レスポンスヘッダにAccess-Control-Allow-Originを付与する
  6. リクエスト元のオリジンhttp://example.jpのCORSが許可されたため、リクエスト元はリソースを受け取ることができる
    image.png

プリフライトリクエストとは

これまでのものは、単純リクエストと呼ばれています。

単純リクエストの要件

メソッドは以下のいずれか

  • GET
  • POST
  • HEAD

設定できるリクエストヘッダは以下のいずれか

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type(以下の要件を満たすもの)

Content-Typeヘッダは以下のいずれか

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

これらの条件を満たすものが単純リクエストです。

単純リクエストではない場合はプリフライトリクエスト

  1. PUTリクエストを送信
  2. PUTメソッドは単純リクエストではないため、事前にプリフライトリクエストが送られる
  3. この時、HTTPメソッドはOPTIONSが使用される
  4. Access-Control-Request-Method: PUTを付与して、PUTでのアクセスをして良いかお伺いをたてる
    image.png

正規のルートの場合

  1. プリフライトリクエストをサーバーが受け取る
  2. Access-Control-Allow-Method: PUT
  3. Access-Control-Allow-Origin: http://api.example.jp
  4. これらをレスポンスヘッダに付与する
  5. 許可が得られたためPUTリクエストが送られる
    image.png
    プリフライトリクエストにはリスクがないのかという疑問がありますが、
    プリフライトリクエストは、クッキーやパラメータが飛ばないのでリスクは極めて小さくなっています。

まとめ

  • 単純リクエストの場合は無条件でHTTPリクエストが送信される
  • 単純リクエストではない場合、先にプリフライトリクエストでお伺いをたててから本番のリクエストを送信して良いか決定する
  • プリフライトリクエスト自体のリスクは極めて小さい

基本的にCORSに関してはフレームワークがいい感じにやってくれるのですが、原理を知って正しく使用していきたいと思います。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?