CORS
CORS (Cross-Origin Resource Sharing)
概要(サマリー)
CORS(Cross-Origin Resource Sharing)とは、異なるオリジン(ドメインやポート番号)のサーバーへのリクエストを、ブラウザが制限・許可する仕組みのことである。たとえば、フロントエンドが http://localhost:3000 で動いているときに、http://localhost:8000 のAPIを呼び出そうとすると「CORSエラー」が発生することがある。初心者がAPIと組み合わせてWebアプリを作り始めたとき、最初にぶつかりやすいエラーのひとつだ。
詳細解説
そもそも「オリジン」とは何か
オリジンとは、URLの「プロトコル・ドメイン・ポート番号」の3つの組み合わせのことである。
| URL | オリジン |
|---|---|
https://example.com/page |
https://example.com |
http://example.com/page |
http://example.com(上とは別) |
https://example.com:8080/page |
https://example.com:8080(上とは別) |
このように、プロトコルやポートが1文字でも違えば「別のオリジン」と見なされる。
なぜブラウザはリクエストを制限するのか
ブラウザには「同一オリジンポリシー(Same-Origin Policy)」と呼ばれるセキュリティの仕組みが組み込まれている。これは、あるオリジンのページが、別オリジンのサーバーから勝手にデータを読み取れないようにするための制限だ。
悪意あるサイトが、別サービスのAPIレスポンスを勝手に読み取る、といった攻撃を防ぐためにある。なお、リクエストの送信自体は発生する場合があるため、ログイン状態を悪用した操作を防ぐには、CORSだけでなくCSRF対策なども重要になる。
CORSはその制限を「許可する」仕組み
CORSは、この制限を必要に応じて解除するための仕組みである。サーバー側が「このオリジンからのリクエストは受け付けますよ」とHTTPヘッダーで宣言することで、ブラウザがリクエストを通してくれるようになる。
代表的なCORSヘッダーは以下のとおりだ。
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Origin: * とすると「すべてのオリジンを許可」という意味になるが、認証情報を扱うAPIでは使えないため注意が必要だ。
CORSエラーが出たときの対処
ブラウザのコンソールに CORS policy という文字が出たら、それはCORSエラーである。このエラーはブラウザが出すものであり、サーバーから応答が返っていても、ブラウザ側でレスポンスの利用がブロックされることがある。
対処の基本は「サーバー側にCORSの許可設定を追加する」ことだ。ただし、fetchやJavaScript側で不要なカスタムヘッダーを付けてプリフライトリクエストを発生させていたり、credentials の設定がサーバー側の許可設定と合っていなかったり、URLやHTTPメソッドが想定と違っていたりする場合もある。AIに「CORSエラーが出る」と伝えると、使っているサーバーの言語やフレームワークに合わせた確認ポイントを提案してくれる。
AIコーディングとCORSの関係
AIが生成したフロントエンドのコードと、別に立てたバックエンドのAPIを接続しようとしたとき、CORSエラーは頻繁に発生する。AIに「CORSエラーが出ています」と伝えれば、バックエンドのCORS設定コードを提案してくれることが多い。ただし、* で全許可するコードを提案されることもあるため、本番環境では許可するオリジンを絞る必要がある点には注意したい。
よくある勘違い
CORSエラーはフロントエンドのコードが原因?
多くの場合、根本原因はサーバー側のCORS設定不足である。ただし、フロントエンド側で不要なヘッダーを追加していたり、認証情報を送る設定とサーバー側の許可設定が噛み合っていなかったりすることもある。基本的には、ブラウザのコンソールだけでなく、実際に送られているリクエストのURL、HTTPメソッド、ヘッダー、サーバー側のレスポンスヘッダーをあわせて確認する。
Access-Control-Allow-Origin: * にすれば全部解決する?
必ずしもそうではない。*(ワイルドカード)はすべてのオリジンを許可するが、Cookie、HTTP認証、クライアント証明書などの認証情報を含むリクエスト(withCredentials: true や credentials: "include")との組み合わせでは使えないというブラウザの制限がある。なお、Authorization ヘッダーでBearerトークンを送るケースは別に考える必要があり、その場合も許可するヘッダーやオリジンを適切に設定することが重要だ。セキュリティ上も、本番環境では必要なオリジンだけを明示的に許可するほうが安全である。
CORSはサーバー間通信でも発生する?
発生しない。CORSはブラウザの機能であるため、Node.jsやPythonなどのサーバー同士が通信する場合には制限されない。CORSが問題になるのは、あくまでブラウザ上のJavaScriptが別オリジンのサーバーを呼び出すケースに限られる。
より詳しくAIに聞いてみよう
- CORSとは何かを、初心者でもわかるように説明してください。
- ブラウザの同一オリジンポリシーがなぜ必要なのか、セキュリティの観点から教えてください。
- Node.js(Express)でCORSを設定する具体的なコードを教えてください。
Access-Control-Allow-Origin: *を本番環境で使ってはいけない理由を教えてください。- AIコーディングでフロントエンドとバックエンドを接続するときのCORSエラーの解決手順を教えてください。