【こーす】

CORS とは?

最終更新:
💡 異なるオリジンの応答を、ブラウザーで読めるようにする仕組み

異なるオリジンへの通信で、サーバーが許可した応答をブラウザー内のスクリプトへ共有する仕組み。HTTPヘッダーで許可を示す。応答を読めないことと、リクエスト自体が送られないことは同じではない。

📌 このページのポイント
プリフライトが必要な通信の例 ブラウザー API ① 事前確認 ② 許可応答 ③ 本リクエスト ④ 本応答 本応答の共有許可も確認する
別オリジンのAPIへ、OPTIONSで事前確認が必要な通信の例。事前確認に失敗すれば本リクエストを送らず、成功しても本応答のCORSヘッダーを確認する。事前確認が不要な通信もある。
ひよこ ひよこ
CORSエラーはなぜ起きるの?
ペンギン先生 ペンギン先生
別オリジンの応答をスクリプトへ共有するための条件に合わないと、ブラウザーは読み取りを許可しないよ。例えばhttp://localhost:3000とhttp://localhost:8080はポートが違うので別オリジン。HTTPとHTTPSの違いも、別オリジンになる理由だね。
ひよこ ひよこ
エラーなら、リクエストは送られていないの?
ペンギン先生 ペンギン先生
そうとは限らないよ。事前確認が不要な通信では、リクエストを送った後で応答の共有が拒否される場合がある。一方、プリフライトという事前確認が必要な通信で、その確認に失敗した場合は本リクエストを送らない。この違いが大切なんだ。
ひよこ ひよこ
どう設定すれば読めるの?
ペンギン先生 ペンギン先生
サーバーがAccess-Control-Allow-Originなど、条件に合うCORSヘッダーを返すようにするよ。「*」で全オリジンへ共有する設定は、認証情報を含めない公開リソースでは使える。公開範囲と通信の条件に合わせて設定するもので、本番では必ず「*」が禁止というわけではないんだ。
ひよこ ひよこ
プリフライトはどんなときに起きるの?
ペンギン先生 ペンギン先生
例えばContent-Typeがapplication/jsonのPOSTや、Authorizationヘッダーを付けるGETでは、OPTIONSで必要な許可を事前に確認するよ。方法だけでなくヘッダーも条件になる。許可が得られて本リクエストを送った後も、本応答を共有できるかの確認が必要なんだ。
ひよこ ひよこ
CORSがあれば、不正なアクセスを防げる?
ペンギン先生 ペンギン先生
CORSの読み取り制限だけで、APIを利用する権限を確認したことにはならないよ。通常のフォームから送れる通信もあるので、CORSだけをCSRF対策にすることもできない。認証・認可や、CSRFトークンなど、サーバー側で必要な対策を組み合わせよう。
もっと詳しく知りたい人へ

Cookie付きの通信で「*」を使えないのはなぜ?

fetchのcredentialsをincludeにするなど、認証情報を含めるモードでは、Access-Control-Allow-Originに具体的なオリジンを指定し、Access-Control-Allow-Credentials: trueも必要だよ。「*」との組み合わせでは応答を共有できない。これはCORSの条件で、Cookieが実際に送れるかにはCookie側の制約なども関係する。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「CORS」って出てきたら「異なるオリジンの応答を、ブラウザーで読めるようにする仕組み」と思えばだいたいOK!
📖 おまけ:英語の意味
「Cross-Origin Resource Sharing」 = オリジン間リソース共有
💬 Cross-Originは異なるオリジンの間、Resource Sharingはリソースの共有という意味だよ。別オリジンだから必ずエラーになるのではなく、サーバー側の許可と通信の条件を確かめるんだ。

参考資料

← 用語集にもどる