0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】CORS(Cross-Origin Resource Sharing)理解

0
Last updated at Posted at 2025-12-24

はじめに

フロントエンドや API を触っていると、必ず一度は見るこのエラー。

Blocked by CORS policy
  • サーバーは 200 OK
  • curl / Postman では普通に動く
  • でもブラウザだけ失敗する

これは バグでも設定漏れでもなく、CORSが正しく動いている結果 です。

CORS とは何か

CORS はサーバーの防御機構ではない。
ブラウザが「レスポンスを読んでよいか」を判断するルールである。

ここを誤解すると、CORS は永久に分かりません。

観点 実際
サーバー どんな Origin からもリクエストは届く
ブラウザ JS にレスポンスを渡すかを判断
curl / Postman CORS を完全に無視

CORS は通信を止めない
読み取りだけを制御する


なぜ CORS が必要なのか

ブラウザには Same-Origin Policy(同一オリジンポリシー) があります。

  • https://a.com の JS は
  • https://b.com のレスポンスを
  • 勝手に読めない

これがなければ、

  • ログイン中の銀行 API
  • 社内システム
  • 個人情報 API

悪意あるサイトから盗み見放題 になります。

しかし現代 Web は、

  • SPA(React / Vue など)
  • API 分離構成
  • フロントとバックが別ドメイン

完全禁止では開発できない

そこで生まれた仕組みが
CORS = 条件付き越境許可

CORS = 条件付き越境許可

CORS は次のような仕組みです。

「このオリジンから来た JS なら、
同一オリジンポリシーを一時的に緩めてよい」
とサーバーが宣言する仕組み

その宣言が、HTTP レスポンスヘッダです。

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

なぜ 200 OK でも JS から読めないのか

GET /user
Origin: https://frontend.example.com
HTTP/1.1 200 OK
{"name":"Alice"}
  • 通信: 成功
  • レスポンス: 返っている

それでも:

JS からは読めない

理由

  • SOP は常に有効
  • CORS ヘッダが無い
  • → SOP の例外が与えられていない

つまり:

読めないのは SOP が通常運転しているだけ

CORS種類

仕様上、CORS は 2 種類しかありません。

種類 内容
シンプルリクエスト 事前確認(OPTIONS)なし
プリフライト付き 事前確認(OPTIONS)あり

1. シンプルリクエスト

危険性が低いと判断され、
ブラウザが「先に聞かずに」送るリクエスト
です。

条件

  • メソッド
    GET / POST / HEAD
  • ヘッダ
    限定的(Authorization 不可)
  • Content-Type
    • text/plain
    • application/x-www-form-urlencoded
    • multipart/form-data

重要

  • 送信は無条件
  • 読み取りは許可制

2. プリフライト(OPTIONS)

先に聞く =
本リクエストの前に、ブラウザがサーバーへ
「これ送っていい?」と確認すること

その確認に使われるのが OPTIONS メソッドです。

OPTIONS は「ブラウザだけ」が送る
  • curl → 送らない(自分で送らない限り)
  • Postman → 送らない
  • ブラウザ → 勝手に送る

だから:

Postman では動くのに、ブラウザでは CORS エラー

が起きる。

なぜ「先に聞く」必要があるのか

ブラウザの立場で考えてみてください。

「この JS、
・PUT で
・Authorization ヘッダ付きで
・JSON を送ろうとしている

もし勝手に送ってダメだったら危ないな…」

だから本番の前に“許可確認”をする
これが プリフライト(Preflight)

CORSヘッダ

CORSヘッダはすべて「ブラウザ向け」
サーバーがブラウザに出す“読み取り許可証”

  • フロントエンドが設定するもの ❌
  • API クライアント(curl 等)が見るもの ❌
  • ブラウザだけが解釈する

CORSヘッダは2種類に分かれる。

① レスポンス側 CORS ヘッダ(最重要)

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

役割

「この Origin の JS なら読んでいい」

重要ルール

  • * は Cookie 使用時 ❌
  • 動的に返す場合は Vary: Origin 必須

Access-Control-Allow-Credentials
Access-Control-Allow-Credentials: true

役割

「Cookie / 認証情報を含めて読んでいい」

注意

Allow-Origin: *
Allow-Credentials: true

ブラウザが強制拒否


Access-Control-Allow-Methods
Access-Control-Allow-Methods: GET, POST, PUT

役割

「どの HTTP メソッドが許可されているか」

  • 主に プリフライトの返答
  • シンプルリクエストでは参照されないことも多い

Access-Control-Allow-Headers
Access-Control-Allow-Headers: Authorization, Content-Type

役割

「どのリクエストヘッダを使っていいか」

  • Authorization を使うなら必須
  • 大文字小文字は区別されない

Access-Control-Expose-Headers
Access-Control-Expose-Headers: X-Total-Count

役割

「JS から読めるレスポンスヘッダを追加で許可」

デフォルトで読めるのはこれだけ

Cache-Control
Content-Type
Expires
Last-Modified
Pragma

Access-Control-Max-Age
Access-Control-Max-Age: 600

役割

「プリフライト結果を何秒キャッシュしていいか」

  • OPTIONS の回数削減
  • パフォーマンス改善に重要

② リクエスト側 CORS ヘッダ(ブラウザ専用)

開発者が直接書くことはほぼない

Origin
Origin: https://frontend.example.com

役割

「私はどこから来た JS です」

  • ブラウザが自動付与
  • curl では自動では付かない

Access-Control-Request-Method
Access-Control-Request-Method: PUT

役割

「これからこのメソッドを使いたい」

  • OPTIONS 専用

Access-Control-Request-Headers
Access-Control-Request-Headers: Authorization

役割

「これらのヘッダを使いたい」

  • OPTIONS 専用

ヘッダ対応関係(ここ超重要)

ブラウザの質問 サーバーの回答
Origin Allow-Origin
Request-Method Allow-Methods
Request-Headers Allow-Headers
Cookie使う? Allow-Credentials

質問と回答が噛み合わないと CORS エラー


最小構成

Cookieなし API

Allow-Origin: https://frontend.example.com
Allow-Methods: GET, POST
Allow-Headers: Content-Type

Cookieあり API

Allow-Origin: https://frontend.example.com
Allow-Credentials: true

まとめ

CORS は門番ではない
図書館の司書である

  • サーバーは本を渡す
  • ブラウザが「読んでいいか」を判断
  • 守っているのはサーバーではなくユーザー

この視点を持つと、
CORS エラーは「意味不明な壁」ではなくなります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?