CORS(Cross-Origin Resource Sharing) こーす
簡単に言うとこんな感じ!
ブラウザが「あなた、よそのサイトのデータを勝手に取りに行こうとしてない?」って見張っててくれる仕組みだよ。その関所を正式に通るための「通行許可証」がCORSなんだ!
CORSとは
CORS(Cross-Origin Resource Sharing)とは、Webブラウザが持つセキュリティの仕組みの一つで、「異なるオリジン(=別のドメインやポート)にあるリソースへのアクセスを、サーバー側が明示的に許可する」ための仕組みです。
Webブラウザにはもともと Same-Origin Policy(同一オリジンポリシー) というルールがあり、あるWebサイトのJavaScriptが「別のドメインのAPIやデータ」を勝手に呼び出すことを原則禁止しています。これは悪意あるサイトが利用者の情報を盗み取るのを防ぐためのものです。しかし現代のWebアプリでは、フロントエンドとバックエンドAPIが別々のドメインに置かれるケースが非常に多く、このルールが邪魔になることがあります。
そこでCORSが登場します。サーバーが「このオリジンからのアクセスは許可するよ」とHTTPレスポンスヘッダーで伝えることで、ブラウザが安全を確認したうえで通信を許可するようになります。CORSはサーバー側の設定で制御するものであり、クライアント(ブラウザ)側の動作はあくまでブラウザが自動的に行います。
CORSの仕組みと「オリジン」の概念
オリジンって何?
オリジン(Origin)とは、スキーム(http/https)+ホスト名+ポート番号 の3点セットのことです。1つでも違えば「別オリジン(Cross-Origin)」と判断されます。
| URL | スキーム | ホスト | ポート | 同一オリジン? |
|---|---|---|---|---|
https://example.com/page | https | example.com | 443 | ✅ 基準 |
https://example.com/other | https | example.com | 443 | ✅ 同じ |
http://example.com/page | http | example.com | 80 | ❌ スキームが違う |
https://api.example.com/page | https | api.example.com | 443 | ❌ ホストが違う |
https://example.com:8080/page | https | example.com | 8080 | ❌ ポートが違う |
CORSリクエストの2種類
CORSには 「シンプルリクエスト」 と 「プリフライトリクエスト」 の2種類があります。
| 種類 | 条件 | 動作 |
|---|---|---|
| シンプルリクエスト | GET / POST(特定のContent-Typeのみ)など条件を満たす場合 | ブラウザがそのままリクエストを送り、レスポンスヘッダーを確認 |
| プリフライトリクエスト | PUT / DELETE や カスタムヘッダーを含む場合など | 本番リクエストの前に OPTIONS メソッドで「事前確認」を行う |
プリフライトリクエストの流れ
ブラウザ APIサーバー
| |
|── OPTIONS /api/data ─────────────────>|
| Origin: https://app.example.com |
| Access-Control-Request-Method: PUT |
| |
|<── 200 OK ──────────────────────────--|
| Access-Control-Allow-Origin: https://app.example.com
| Access-Control-Allow-Methods: PUT |
| |
|── PUT /api/data ────────────────────>| ← 本番リクエスト
| |
|<── 200 OK + データ ─────────────────--|
覚え方:「CORS=関所の通行許可証」
🏯 Same-Origin Policy = 「よそ者お断り」の関所
📜 CORSヘッダー = 「このお侍は通してよい」という藩主(サーバー)の許可状
🔍 ブラウザ = 許可状を確認する関所の番人
主要なCORS関連HTTPヘッダー
CORSはHTTPヘッダーのやりとりで実現されます。
| ヘッダー名 | リクエスト/レスポンス | 役割 |
|---|---|---|
Origin | リクエスト | ブラウザが自動付与。送信元オリジンを伝える |
Access-Control-Allow-Origin | レスポンス | 許可するオリジンを指定(* で全許可も可) |
Access-Control-Allow-Methods | レスポンス | 許可するHTTPメソッドを列挙 |
Access-Control-Allow-Headers | レスポンス | 許可するリクエストヘッダーを列挙 |
Access-Control-Allow-Credentials | レスポンス | Cookie等の認証情報の送信を許可するか |
Access-Control-Max-Age | レスポンス | プリフライト結果のキャッシュ時間(秒) |
Access-Control-Request-Method | プリフライト | 本番リクエストで使うメソッドを事前申告 |
Access-Control-Request-Headers | プリフライト | 本番リクエストで使うヘッダーを事前申告 |
歴史と背景
- 1995年頃 — JavaScriptがブラウザに登場。当初はページ内の簡単な処理のみで、外部リソースへのアクセスは想定外
- 2000年代前半 —
XMLHttpRequest(XHR)の登場でAjax通信が普及。Same-Origin Policyが重要な防御線に - 2004〜2006年 — Webアプリの高度化に伴い、異なるオリジン間通信の需要が急増。
<script>タグを悪用したJSONP(JSON with Padding)が苦肉の策として使われる - 2009年 — W3CがCORSの仕様策定を開始
- 2014年 — W3Cが CORS仕様を正式勧告(W3C Recommendation)
- 2017年 — Fetch Living Standard(WHATWG)にCORSが統合され、より現代的な形で整備
- 2020年代 — マイクロサービス・SPA(Single Page Application)の普及でCORSエラーは開発者が最もよく遭遇するエラーの一つに
CORSと関連技術の比較・整理
CORSとJSONPの違い
CORS登場前は JSONP(JSON with Padding) という回避策が使われていましたが、現在は非推奨です。
| 比較項目 | CORS | JSONP |
|---|---|---|
| 対応メソッド | GET / POST / PUT / DELETE など全て | GET のみ |
| セキュリティ | サーバーが明示的に許可 | 任意のスクリプトを実行できる(危険) |
| エラーハンドリング | 可能 | 困難 |
| 現在の推奨 | ✅ 推奨 | ❌ 非推奨 |
関連する規格・RFC
| 規格・RFC番号 | 内容 |
|---|---|
| RFC 6454 | Web Originの概念を定義した標準仕様 |
| Fetch Living Standard | CORSを含むブラウザのfetch仕様(WHATWG) |
関連用語
- Same-Origin Policy — ブラウザが持つ「同一オリジンしか信用しない」セキュリティの大原則
- HTTPヘッダー — HTTPリクエスト・レスポンスに付随するメタ情報。CORSはヘッダーのやりとりで実現される
- プリフライトリクエスト — 本番リクエスト前にブラウザが自動で送る事前確認のOPTIONSリクエスト
- REST API — CORSエラーが最も多く発生する、フロントエンドとバックエンド間のAPI通信
- CSP(Content Security Policy) — CORSと並ぶブラウザのセキュリティ機構。読み込めるリソースの出所を制限する
- JSONP — CORS以前に使われた異なるオリジンへのアクセス回避策。現在は非推奨
- SPA(Single Page Application) — CORSの設定が必須になるケースが多いフロントエンドアーキテクチャ
- OAuth 2.0 — CORS設定と組み合わせて使われることが多い認証・認可の仕組み