PR

【JavaScript】CORSとは?Access-Control-Allow-Originの意味を初心者向けに解説

CORSの記事アイキャッチ。WebアプリのイラストとCORSの文字。 JavaScript

CORSとは、ブラウザで動くJavaScriptが、別オリジンのAPIレスポンスを読めるかどうかを、サーバーのHTTPヘッダーで判断する仕組みです。

たとえば、https://app.example.com の画面から https://api.example.com のAPIを fetch() で呼び出すと、ブラウザは「この別の場所から返ってきたレスポンスをJavaScriptへ渡してよいか」を確認します。

CORSエラーは、通信が一切サーバーへ届いていないという意味ではありません。多くの場合、ブラウザがレスポンスをJavaScriptへ渡さない状態です。

この記事では、CORSの意味、オリジンの考え方、Access-Control-Allow-Origin の役割、プリフライト、よくある直し方を初心者向けに整理します。

スポンサーリンク

まず結論:CORSは別オリジンAPIの受付ゲート

CORSは、Cross-Origin Resource Sharingの略です。日本語では「オリジン間リソース共有」と説明されますが、最初は 別のオリジンにあるAPIのレスポンスを、ブラウザ上のJavaScriptが読めるようにするための許可ルール と考えると分かりやすいです。

重要なのは、CORSの判断をしている中心がブラウザだという点です。サーバーはレスポンスに許可ヘッダーを付け、ブラウザはそのヘッダーを見て、JavaScriptへレスポンスを渡すかどうかを決めます。

次の図では、画面のJavaScript、ブラウザ、APIサーバーの間にある「受付ゲート」としてCORSを見てください。どこで許可を確認しているかを押さえると、エラーの読み方が変わります。

フロントエンド、ブラウザ、APIサーバー、CORS許可ヘッダーの関係を示す図
CORSは、別オリジンAPIのレスポンスをブラウザ上のJavaScriptへ渡してよいかを確認する受付ゲートです。

CORSエラーが出る典型例

CORSエラーは、フロントエンドとAPIを別々の場所で動かすとよく出ます。学習中なら、ReactやVueなどの開発サーバーが http://localhost:3000、APIサーバーが http://localhost:8080 という構成で起きやすいです。

fetch("http://localhost:8080/api/users")
  .then((response) => response.json())
  .then((users) => console.log(users));

このコード自体が間違っているとは限りません。問題は、ブラウザから見ると localhost:3000localhost:8080 はポートが違うため、別オリジンとして扱われることです。

そのためAPIサーバー側が、http://localhost:3000 からの読み取りを許可するヘッダーを返さないと、ブラウザはJavaScriptにレスポンスを渡しません。

オリジンとは何か

オリジンとは、Web上の出どころを表す単位です。MDNの同一オリジンポリシーの説明でも、オリジンはスキーム、ホスト、ポートの組み合わせとして扱われます。

スキームは httpshttp、ホストは example.com のような名前、ポートは 4433000 のような番号です。どれか1つでも違うと、ブラウザは別オリジンとして扱います。

次の図では、オリジンを3点セットとして見てください。CORSエラーの原因を探すときは、ドメインだけでなく、httphttps の違いやポート番号の違いも確認します。

同一オリジンと別オリジンをスキーム、ホスト、ポートで比較する図
オリジンは、スキーム、ホスト、ポートの3点で決まり、1点でも違うと別オリジンです。
比較判定
同じhttps://example.com/apphttps://example.com/apiスキーム、ホスト、ポートが同じなので同一オリジン
スキーム違いhttp://example.comhttps://example.comhttpとhttpsが違うので別オリジン
ホスト違いhttps://app.example.comhttps://api.example.comホスト名が違うので別オリジン
ポート違いhttp://localhost:3000http://localhost:8080ポートが違うので別オリジン

同一オリジンポリシーとCORSの関係

ブラウザには、同一オリジンポリシーという重要なセキュリティの仕組みがあります。これは、あるオリジンで読み込まれた文書やスクリプトが、別オリジンのリソースへ自由にアクセスしないように制限する考え方です。

もしこの制限がなければ、悪意のあるページが、利用者がログイン中の別サイトの情報をブラウザ経由で読み取れてしまう可能性があります。CORSは、この制限を壊す仕組みではなく、サーバーが明示的に許可した範囲だけ例外を作る仕組みです。

つまり、同一オリジンポリシーは基本のブレーキ、CORSはサーバーが許可した相手だけに開くゲートです。

CORSの流れ

CORSでは、ブラウザがリクエストに Origin ヘッダーを付けることがあります。APIサーバーは、そのOriginを見て、許可する場合はレスポンスに Access-Control-Allow-Origin を返します。

次の図では、Origin、許可ヘッダー、ブラウザの照合、JavaScriptへの受け渡しの順番を見てください。CORSの主役が「ブラウザの照合」であることが分かります。

Originヘッダー、Access-Control-Allow-Origin、ブラウザ判定の流れを示す図
CORSでは、APIサーバーの許可ヘッダーをブラウザが照合し、JavaScriptへレスポンスを渡すか判断します。
Origin: https://app.example.com

Access-Control-Allow-Origin: https://app.example.com

上のように、リクエスト元のOriginと、レスポンスの Access-Control-Allow-Origin が対応していれば、ブラウザはレスポンスをJavaScriptへ渡せます。対応していなければ、コンソールにCORSエラーが表示されます。

Access-Control-Allow-Originの意味

Access-Control-Allow-Origin は、APIサーバーが「このオリジンのJavaScriptには、レスポンスを読ませてよい」とブラウザへ伝えるレスポンスヘッダーです。

開発中にすべてを許可したくなり、* を設定する例を見ることがあります。公開APIのように誰が読んでもよいリソースでは選択肢になりますが、ログイン情報やCookieを含むリクエストでは注意が必要です。

Access-Control-Allow-Origin: https://app.example.com
Vary: Origin

特定の画面からだけAPIを読ませたい場合は、上のように具体的なオリジンを返します。複数のオリジンを許可する場合でも、レスポンスには実際のリクエスト元に対応した1つのオリジンを返す実装が一般的です。

また、Cookieなどの認証情報を含める場合は、Access-Control-Allow-Credentials: true やJavaScript側の credentials: "include" も関係します。この場合、Access-Control-Allow-Origin: * を安易に使えない点に注意します。

プリフライトとは何か

プリフライトとは、本番のリクエストを送る前に、ブラウザが OPTIONS メソッドで事前確認する仕組みです。すべてのCORSリクエストで必ず発生するわけではありません。

たとえば、PUTDELETE、独自ヘッダー、JSONの Content-Type: application/json などが関係すると、ブラウザは先に「このメソッドやヘッダーで送ってよいか」をAPIサーバーへ確認することがあります。

次の図では、プリフライトを「受付での事前確認」として見てください。OPTIONSが失敗すると、本番のPOSTやPUTの前に止まって見えることがあります。

OPTIONSプリフライト、本番リクエスト、許可ヘッダーの関係を示す図
プリフライトは、本番リクエストの前にブラウザがOPTIONSで許可を確認する事前確認です。
OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type

APIサーバーは、この事前確認に対して、許可するメソッドやヘッダーを返します。ここで必要なヘッダーが不足していると、ブラウザは本番リクエストへ進めません。

CORSエラーの直し方

CORSエラーが出たときは、まずブラウザのConsoleだけで判断せず、Networkタブで実際のリクエストとレスポンスヘッダーを見ます。特に、OriginAccess-Control-Allow-Origin、プリフライトの OPTIONS を確認します。

次の図では、CORSエラーを調べる順番を見てください。フロントエンドの fetch() を何度も書き換える前に、APIサーバーがどのヘッダーを返しているかを確認するのが近道です。

CORSエラーの原因調査をブラウザ、ネットワーク、レスポンスヘッダー、サーバー設定の順に見る図
CORSエラーは、Console、Network、レスポンスヘッダー、サーバー設定の順で見ると原因を切り分けやすくなります。
  • Consoleで、拒否されたOriginとURLを読む
  • Networkで、OPTIONSが出ているか、本番リクエストまで進んでいるかを見る
  • レスポンスにAccess-Control-Allow-Originがあるか確認する
  • 許可したいOriginが、実際のOriginと完全一致しているか確認する
  • Cookieを使う場合は、credentials設定とAllow-Credentialsを合わせて確認する

根本的な修正は、多くの場合APIサーバー側で行います。フロントエンド側でCORSヘッダーを追加しても、ブラウザが見ているのはAPIサーバーから返ってくるレスポンスヘッダーです。

CORSと認証・CSRF対策の違い

CORSはセキュリティに関係しますが、認証や権限チェックそのものではありません。CORSを許可したからといって、ログイン不要で何でも見せてよいという意味にはなりません。

認証は、利用者が誰かを確認する仕組みです。権限チェックは、その利用者がそのデータを見たり操作したりしてよいかを判断する仕組みです。CSRF対策は、利用者のブラウザを勝手に使った操作を防ぐための仕組みです。

次の図では、CORS、認証、CSRF対策の役割を分けて見てください。CORSは「読む許可」の話であり、本人確認や権限確認の代わりではありません。

CORS、認証、CSRF対策の役割の違いを分けて示す図
CORSはレスポンスを読めるかの判定であり、認証やCSRF対策とは役割が違います。

既存記事とあわせて読む順番

CORSは、JavaScriptの fetch()、HTTPヘッダー、Web APIの理解とつながっています。先にAPIやHTTPの用語を押さえておくと、CORSエラーの原因を読みやすくなります。

公式情報と確認先

仕様として確認する場合は、WHATWG Fetch StandardとMDNのCORS、同一オリジンポリシーの説明を参照します。Fetch Standardは、fetch、CORSプロトコル、リダイレクトなど、ブラウザの取得処理を一貫した仕組みとして定義しています。

まとめ

CORSは、別オリジンのAPIレスポンスをブラウザ上のJavaScriptが読めるかどうかを、サーバーのHTTPヘッダーで判断する仕組みです。

  • CORSは、別オリジンのレスポンスを読めるかを決めるブラウザ中心の仕組み
  • オリジンは、スキーム、ホスト、ポートの3点で決まる
  • Access-Control-Allow-Originは、APIサーバーが許可するOriginをブラウザへ伝えるヘッダー
  • プリフライトは、本番リクエスト前のOPTIONSによる事前確認
  • CORSは認証や権限チェックの代わりではない

CORSエラーが出たら、まずConsole、Network、レスポンスヘッダー、サーバー設定の順に見ます。フロントエンドだけで解決しようとせず、APIサーバーが正しい許可ヘッダーを返しているかを確認しましょう。

タイトルとURLをコピーしました