CORSって何?
CORS: Cross-Origin Resource Sharing
オリジン間リソース共有
オリジンって何?
同じところからのリクエストであるかを判別するための方法
URIの、scheme、host、portが一致していると、それは「同一オリジン」である
scheme、host、portとか、URIの呼称については、こちらを参照
どういう時に使うの?
異なるオリジンにAjaxリクエストやWebフォントの読み込みを行う際に使われる
なんで必要なの?
悪意あるサイトがAjaxで勝手にどこかAPIを叩けないよう、同一オリジン以外へのリクエストはブロックされるようになっている
- これを、Same Origin Policy(同一オリジンポリシー) と呼ぶ
ただし、異なるオリジンにリクエストを投げる必要もあるため、CORS という仕組みが生まれた
どういう風にやるの?
単純リクエストという方式の場合、以下のような流れ
- ブラウザ側からリクエスト。リクエストヘッダの中に
Origin
が含まれるOrigin
は、リクエストの発生元がどこであるかを示す
- サーバ側からレスポンス。レスポンスヘッダの中に
Access-Control-Allow-Origin
が含まれるAccess-Control-Allow-Origin
はサーバが許可するオリジンを入れる*
の場合は「すべて許可」となるが、非常に脆弱なのでやめるべき- 複数の値を含めることはできない。許可すべきオリジンが複数ある場合は、サーバ側で制御する
- ブラウザ側で
Origin
とAccess-Control-Allow-Origin
が一致していれば、処理が行われる
プリフライトリクエスト
クロスオリジンのリクエストが いろいろな条件を満たさなかった場合、上記の単純リクエストではなく、プリフライトリクエストが行われる
ユーザーデータに影響を与える可能性があるようなリクエストの場合、プリフライトが行われる(らしい)
プリフライトリクエストの流れ
OPTIONS
メソッドをつかって、事前に安全にクロスオリジンの通信が行えるかチェックする
以下のような流れ
- ブラウザ側で、
OPTIONS
メソッドで以下のリクエストを投げるOrigin
: 単純リクエストと同じAccess-Control-Request-Method
: 送るメソッドAccess-Control-Request-Headers
: 送るリクエストヘッダ
- サーバ側からレスポンスを投げる。その時、以下のレスポンスヘッダを含む
Access-Control-Allow-Origin
: 単純リクエストと同じAccess-Control-Allow-Methods
: 許可するメソッドAccess-Control-Allow-Headers
: 許可するリクエストヘッダAccess-Control-Max-Age
: プリフライトリクエストの結果をキャッシュして良い時間(秒)
- ブラウザ側でレスポンスヘッダを読み込んで、問題なさそうならば実際のリクエストを開始する
資格情報を含むリクエスト
標準では cookie や basic 認証を含むリクエストに関わる情報は送信されない
そのためには、JavaScript 側で withCredentials
というオプションを true
にする必要がある
さらに、cookie の情報をやり取りしたい場合は、レスポンスヘッダに Access-Control-Allow-Credentials: true
をつけて、許可する必要がある
また、Set-Cookie
については、サードパーティCookieと同じく、ドメインが異なるとブラウザの設定によっては読み込めない
あと、 資格情報を含むリクエストの場合 Access-Control-Allow-Origin
に *
は使えない