目次
CORS(クロスオリジン・リソース・シェアリング)完全解説
〜なぜエラーが起きるのか、どんな意味があるのか〜
はじめに
みなさん、フロントエンド開発をしていて「CORSエラー」という赤文字に悩まされたことはありませんか? 自分で作ったAPIなのに、XMLHttpRequest (XHR) や fetch でアクセスすると「Access-Control-Allow-Originが設定されていない」とエラーになる。そんな経験をした方は多いと思います。
💡 よくある場面: ローカル開発でhttp://localhost:3000からhttp://localhost:5000のAPIにアクセスしようとして、突然CORSエラーが発生する。
今日はこの CORS(Cross-Origin Resource Sharing, クロスオリジン・リソース・シェアリング) について、順を追って学んでいきましょう。
この記事で学べること
- そもそもCORSとは何か
- なぜ必要なのか
- どのように働いているのか
- 歴史的な背景
- API設計で気をつけるべき点
1. そもそも「オリジン」とは?
まずCORSを理解する前に、「オリジン」という言葉を押さえましょう。 オリジン(origin) とは、Web上での「出所(プロトコル・ドメイン・ポートの組み合わせ)」を指します。
オリジンの構成要素
オリジンは以下の3つの要素で構成されています:
- プロトコル(http/https)
- ドメイン(example.com)
- ポート番号(:80, :443, :3000など)
具体例で理解する
https://example.com:443http://example.com:80https://api.example.com:443
例を挙げると:
これらは、たとえ同じ「example.com」でもプロトコルやポートが違えば別オリジンとして扱われます。
🎯 重要: ブラウザはこの3つの組み合わせが完全に一致する場合のみ「同一オリジン」と判断します。
2. なぜCORSという仕組みが必要なのか?
ここで質問です。 もしブラウザが制限なくどんなサイトのリソースにもリクエストできるとしたら、何が起きるでしょうか?
想定される危険なシナリオ
- 悪意あるサイトにアクセスしたユーザーのブラウザが、自動的にユーザーの銀行サイトへリクエストを飛ばす。
- ユーザーが気づかないうちに、個人情報や決済情報が外部に流出する。
シナリオ1: 悪意あるサイトからの攻撃 → ユーザーがログイン済みなら、そのCookie情報が勝手に送信されてしまう。
- ソーシャルメディアの投稿を勝手に取得
- メールの内容を読み取る
- オンラインショッピングの履歴を盗む
シナリオ2: データの不正取得
同一オリジンポリシーの役割
こうした クロスサイトリクエストフォージェリ(CSRF) 的な攻撃を防ぐために、ブラウザは「同一オリジンポリシー(Same-Origin Policy)」というルールを守ります。
🛡️ 同一オリジンポリシー: 自分のオリジン以外に対しては勝手に通信しない
しかし困ることもある
しかし実際には、フロントエンド(https://myapp.com)とAPIサーバー(https://api.myapp.com)が別オリジンになるケースはよくあります。
このままでは正しい通信すらブロックされてしまう…。 そこで登場したのが CORS です。
💡 CORSの役割: サーバーが「このオリジンからのアクセスは安全です」とブラウザに伝える仕組み
3. CORSの仕組み
CORSは、サーバーが「このオリジンからのアクセスはOKですよ」とブラウザに伝える仕組みです。
基本的な流れ
- フロントエンドが別オリジンのAPIにリクエストを送信
- ブラウザが「この通信は安全?」とサーバーに確認
- サーバーが「このオリジンは許可します」と返答
- ブラウザが通信を許可
重要なHTTPヘッダー
そのための代表的なHTTPヘッダーがこちら:
Access-Control-Allow-Origin: https://myapp.com
これが返ってくれば、ブラウザは通信を許可します。 逆に書かれていなければ「CORSエラー」となります。
その他の重要なヘッダー
Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Allow-Credentials: true
✅ 成功の条件: サーバーが適切なCORSヘッダーを返すことで、ブラウザが通信を許可します。
4. プリフライトリクエストとは?
ここでよく疑問に思われるのが「プリフライトリクエスト」です。 これは 事前確認のリクエスト のことです。
プリフライトが必要な場合
GETメソッドHEADメソッドPOSTメソッド(特定の条件のみ)- 標準的なヘッダーのみ使用
PUTDELETEなど「副作用のある」メソッド- 独自ヘッダーを送る場合
Content-Type: application/jsonなど
プリフライト不要(シンプルリクエスト)
プリフライト必要(複雑なリクエスト)
プリフライトの流れ
このときブラウザは、まず以下のような OPTIONS リクエストをサーバーに送ります:
OPTIONS /api/data HTTP/1.1 Origin: https://myapp.com Access-Control-Request-Method: DELETE Access-Control-Request-Headers: Content-Type
サーバーはこれに対して、
Access-Control-Allow-Origin: https://myapp.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type
と返せば、本リクエストが実行されます。
🔄 プリフライトの目的: ブラウザが「このリクエストは安全に実行できますか?」と事前に確認すること
5. 歴史と標準化の経緯
CORSは、W3C(World Wide Web Consortium) によって標準化が進められ、2014年に勧告されました。
Ajax革命の時代
背景には、Ajax(非同期通信)の普及があります。2000年代半ば、Google MapsやGmailなどが登場し、ブラウザからAPIを叩くことが急速に増えました。
しかし「同一オリジンポリシー」があるため、当初は外部APIと連携するのが難しく、開発者は次のような工夫をしていました:
当時の迂回策
- scriptタグ経由でデータ取得
- セキュリティリスクが高い
- エラーハンドリングが困難
- 自前サーバーを経由させる
- サーバーリソースを消費
- 設定が複雑
JSONP(JSON with Padding)
リバースプロキシ
CORSの誕生
こうした迂回策の不便さを解消するために、CORSが導入されたのです。
📅 歴史的意義: CORSにより、Webアプリケーションの可能性が大幅に広がりました。
6. よくある開発現場でのつまずき
ケース1:ローカル環境でのテスト
問題: http://localhost:3000 → http://api.localhost:5000 この場合も別オリジン扱いとなり、CORSエラーが出ます。
- 開発時はAPI側で
Access-Control-Allow-Origin: *を一時的に許可 - リバースプロキシを立てる
- Next.jsの
next.config.jsでプロキシ設定
解決策:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'http://localhost:5000/api/:path*'
}
]
}
}ケース2:本番環境での設定漏れ
問題: APIサーバーにCORSヘッダーが設定されていないと、フロントからは必ずエラーになります。
- Nginx:
nginx.confの設定 - Express: CORSミドルウェアの設定
- Django:
django-cors-headersの設定 - CloudFront: レスポンスヘッダーの設定
確認すべき箇所:
ケース3:認証付きAPIでの問題
問題: CookieやAuthorizationヘッダーを使う場合、追加設定が必要
必要な設定:
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://myapp.com // *は使えない
⚠️ 注意:Access-Control-Allow-Credentials: trueの場合、Access-Control-Allow-Originに*は使用できません。
7. CORSのメリット・デメリット
メリット
- 不正なクロスサイト通信を防ぎ、ユーザーを守る
- CSRF攻撃などの脅威から保護
- サーバー側でアクセス制御が可能
- 外部API連携を安全に実現できる
- マイクロサービス間の通信が可能
- フロントエンドとバックエンドの分離が容易
セキュリティの向上
開発の柔軟性
デメリット
- 設定が複雑で初心者がつまずきやすい
- サーバー側の知識が必要
- デバッグが困難な場合がある
- プリフライトによる通信回数増加
- レスポンス時間の若干の増加
- ネットワーク帯域の消費
設定の複雑さ
性能への影響
⚖️ バランス: セキュリティと利便性のバランスを取る仕組みとして設計されています。
8. 最新の状況とブラウザ対応
ブラウザサポート状況
2025年現在、主要ブラウザ(Chrome, Firefox, Safari, Edge)はすべてCORSを実装しています。 一部仕様解釈に差はありますが、基本的な挙動は共通化されており、開発者は安心して使えます。
セキュリティ強化の流れ
特にセキュリティ強化の流れとして:
SameSite Cookie属性との併用
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure
- CORSでオリジンを制限
- CSRFトークンでリクエストの正当性を確認
- 二重のセキュリティ対策
CORSとCSRFトークンの組み合わせ
今後の展望
- WebAssemblyとの連携強化
- Service WorkerでのCORS制御
- HTTP/3での最適化
🔮 将来性: CORSは今後もWebセキュリティの基盤として重要な役割を果たし続けます。
9. API設計での注意点
みなさんがAPIを設計・開発する際には、以下に注意してください:
セキュリティの原則
1. 許可するオリジンを最小限に
// ❌ 危険 Access-Control-Allow-Origin: * // ✅ 安全 Access-Control-Allow-Origin: https://myapp.com
2. 必要なHTTPメソッドとヘッダーだけを許可
// ❌ 過度に広い許可 Access-Control-Allow-Methods: * // ✅ 必要最小限 Access-Control-Allow-Methods: GET, POST
3. 認証が絡む場合は特に注意
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://myapp.com // *は使えない
実装時のチェックリスト
- [ ] 本番環境では
*を使用していない - [ ] 必要なメソッドのみ許可している
- [ ] 認証が必要な場合は
credentials: trueを設定 - [ ] プリフライトリクエストに対応している
- [ ] エラーハンドリングが適切に実装されている
🛡️ セキュリティファースト: 便利さよりも安全性を優先することが重要です。
まとめ
CORSとは何かを一言でまとめると、 「ブラウザがユーザーを守るために設けた"通信のルール"を、サーバーが許可する仕組み」 です。
この記事で学んだこと
- オリジンとは何か(プロトコル・ドメイン・ポートの組み合わせ)
- 同一オリジンポリシーがなぜ必要なのか(セキュリティ保護)
- CORSでどのように制御しているのか(サーバー側の許可)
- プリフライトリクエストの意味(事前確認)
- 歴史的な背景と最新の状況(Ajax革命から現在まで)
実践的な理解
これらを理解しておけば、CORSエラーに出会っても「なるほど、サーバー側がこう返していないからだな」と冷静に判断できるでしょう。
重要なポイント
ネイティブアプリやサーバーサイドではCORSは基本的に関係ありません。これはあくまで「ブラウザの仕様」 だからです。
みなさんも次にCORSエラーを見かけたら、「ブラウザが安全確認をしてくれているんだ」と思い出してください。
最後に
CORSは複雑に見えますが、その背景には「ユーザーの安全を守る」という重要な目的があります。 適切に理解し、実装することで、安全で使いやすいWebアプリケーションを作ることができるのです。
💡 覚えておいてください: CORSエラーは「問題」ではなく、「ブラウザが正常に働いている証拠」です。
関連記事
APIキーの取り方からWeb実装まで — OpenAI / Claude(Anthropic) / Amazon Bedrockを“手を動かす人”向けにやさしく解説
生成AI APIを実務のWebアプリに安全に組み込むための実践ガイド。キーの取得、認証、最小コード例、料金の考え方、Next.jsでの安全な組み込みパターン、運用のコツまで網羅。
Next.js と Node.js――歴史の片鱗から最新活用まで
Next.js と Node.js の歴史から最新の活用方法まで、React 時代のフルスタック開発を段階的に解説。初心者でも理解できる実践的なガイドです。
OIDCって何?どう違う?なぜ"すごい"のか(AWS×GitHubの実例つき徹底講義)
OIDC(OpenID Connect)について、ゼロから体系的に学びます。OAuth2.0やSAMLとの違い、AWSとGitHubでの実装例まで、実例と図解で丁寧に解説します。
VPNとは何か?クラウド時代のVPN活用と中国での現状
VPNの基本からクラウドサービスでの活用、中国での特殊な状況まで、初心者にも分かりやすく解説します。セキュリティとプライバシーを守る技術の全体像を理解できます。
悪質なWeb広告の実態と被害を避けるための完全ガイド
恐怖を煽るウイルス警告やサブスク詐欺など悪質なWeb広告の手口・背景・対策を整理し、個人とサイト運営者が取るべき行動を解説します。