CORS調べてみた
これなに
セキュリティの仕組みの1つであるCORSを調べてみました。
CORSとは
cross-origin-resource-sharingの略で、日本語ではオリジン間リソース共有といいます。
文字通り異なるオリジン間でリソースを共有する、つまりアクセスを許可する仕組みになります。
ブラウザでは同一オリジンポリシーが働き、異なるオリジンにアクセスすることは基本的にはできませんでした。
しかし、時には異なるオリジン上のコンテンツを利用したい場合があるかと思います。
そのような時は、CORSによって異なるオリジン間のアクセスを許可します。
以下で詳しく紹介しますが、CORSというのは異なるオリジン間でアクセスを可能にするために、リクエスト側とレスポンス側で違いにアクセスのルールなどを確認し合う仕組みとイメージしてください。
(オリジンや同一オリジンポリシーについてはこちらをご参照ください)
CORSのパターン
CORSには大きく単純なリクエストとプリプライトリクエストの2つのパターンがあります。
以下それぞれを紹介します。
単純なリクエスト
※「単純なリクエスト」という言い方は正式な呼び方ではないため、この記事内特有であることをご注意ください。
単純なリクエストの場合、 レスポンス側でアクセスを許可するオリジンを設定することで CORSが可能になります。
具体的には以下のヘッダーをレスポンスに追加します。
Access-Control-Allow-Origin: オリジン名 // ex) https://tech-tech.blog
単純なリクエストの条件
CORSにおける簡単なリクエストとは以下の条件に一致するものになります。
- 以下のメソッドである
- GET
- POST
- HEAD
- 手動で設定されたヘッダーは以下である
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Content-Typeは以下のみが設定されている
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- XMLHttpRequestの場合、
オブジェクト.upload.addEventListener()
が使用されていない - リクエストに
ReadableStream
が使われていない
プリフライトリクエスト
プリフライトリクエストとは、通常のリクエストの前にOPTIONSリクエストを送信し、通常のリクエストを送信しても問題がないかどうかを検証するリクエストになります。
単純なリクエストの条件に一致しないリクエストは、プリフライトリクエストとして処理されます。
プリフライトリクエストでは、以下のヘッダーががリクエストとして送信されます。
- Access-Control-Request-Method
- Access-Control-Request-Headers
- Origin
レスポンスヘッダーでこれらのリクエストに対して許可します。
以下はhttps://tech-tech.blogにPUTメソッドを送信した場合の例になります。
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT
Access-Control-Allow-Headers: ex) Content-Type
Access-Control-Allow-Origin: ex) https://tech-tech.blog
Access-Control-Max-Age: ex) 86400
上記のヘッダーをアプリケーション内で明示的に実装することで CORSが可能になります。
認証情報を含んだリクエスト
クロスドメインに対するリクエストは通常、cookie情報など認証情報は含まれません。
そのため、認証情報を含ませるためには明示的に設定する必要があります。
以下はXMHttpRequestの例になります。
var request = new XMLHttpRequest();
request.withCredentials = true;
レスポンス側でも認証情報を扱うことを明示的に許可する必要があります。
以下ヘッダーをレスポンスヘッダーに追加します。
Access-Control-Allow-Credentials: true;
これで CORSで認証情報を扱うことができます。
以上!!!!!!!
参照
「体系的に学ぶ安全なWebアプリケーションの作り方」徳丸 浩著