よく見るエラー
Access to XMLHttpRequest at 'http://example:3000' from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
同一オリジンポリシー(Same-Origin Policy)とは
- CSRF等の攻撃を防ぐため、異なるオリジンのリソースへのアクセスに制約をかける考えかた。
同一オリジンの判定
- プロトコル、ホスト、ポート番号の組み合わせが等しい場合は、同一オリジンとなる。
具体例として http://www.example.com に対しては、
http://www.example.com/example.png // 一致(パスが異なるだけ)
https://www.example.com/example.png // スキーム
不一致
http://www2.example.com/example.png // ホスト
不一致
http://www.example.com:3000/example.png // ポート
不一致
IEの場合は以下の二つの例外があり。
- 信頼済みゾーン : 双方のドメインが高く信頼されたゾーン (企業のドメインなど) である場合は、同一オリジンの制限が適用されない。
- ポート番号 : 同一オリジンの確認要素にポート番号を含まない。
同一オリジンポリシーの制約を受けるWebAPI
- XMLHttpRequest
- Canvas
- Web Storage
- X-Frame-Options
同一オリジンポリシーの制約を受けないリソース取得
- script // スクリプト
- img, video, audio // メディア
- object, embed, applet // プラグイン
- frame, iframe // 別サイトのコンテンツ
- link, CSS(font-face): // CSS、Webフォントなど
CORS(Cross-Origin Resource Sharing)とは
- 異なるオリジン間でのリソース共有の手法
- 新たなリクエストヘッダーをサーバー側で付加することで作用する。
Access-Control-Allow-Origin: https://example.co.jp // 特定のサイトを許可する
Access-Control-Allow-Origin: * // 全てのサイトを許可する
Access-Control-Allow-Headers "X-Requested-With, Origin, X-Csrftoken, Content-Type, Accept"
CORS対応(単純リクエストの場合)
以下の条件を全て満たす場合、クロスオリジンのリクエストは受付可能
- HTTPメソッドが下記のいずれか。
- GET
- POST
- HEAD
- HTTPヘッダに下記以外のフィールドが含まれない。
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Typeの値は下記のいずれか。
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
CORS対応(プリフライトリクエストの場合)
単純リクエストと異なる場合、プリフライトリクエスト (Preflight Request)を先に送り、
実際にリクエストしても良いか確認する。
以下の場合、標準外の Ping-Other HTTP リクエストヘッダーを設定しているので、
プリフライトリクエストの通信が先に行われる。
参考:https://developer.mozilla.org/ja/docs/Web/HTTP/CORS