CORS(クロスオリジン・リソース・シェアリング)完全解説

CORSエラーの原因から解決方法まで、フロントエンド開発者向けに分かりやすく解説。同一オリジンポリシーからプリフライトリクエストまで網羅的に紹介します。

公開日: 2025年9月10日
読了時間: 7
著者: ぽちょ研究所
読了時間: 7

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つの要素で構成されています:

  1. プロトコル(http/https)
  2. ドメイン(example.com)
  3. ポート番号(:80, :443, :3000など)

具体例で理解する

  • https://example.com:443
  • http://example.com:80
  • https://api.example.com:443
  • 例を挙げると:

    これらは、たとえ同じ「example.com」でもプロトコルやポートが違えば別オリジンとして扱われます。

🎯 重要: ブラウザはこの3つの組み合わせが完全に一致する場合のみ「同一オリジン」と判断します。

2. なぜCORSという仕組みが必要なのか?

ここで質問です。 もしブラウザが制限なくどんなサイトのリソースにもリクエストできるとしたら、何が起きるでしょうか?

想定される危険なシナリオ

  1. 悪意あるサイトにアクセスしたユーザーのブラウザが、自動的にユーザーの銀行サイトへリクエストを飛ばす。
  2. シナリオ1: 悪意あるサイトからの攻撃 → ユーザーがログイン済みなら、そのCookie情報が勝手に送信されてしまう。

  3. ユーザーが気づかないうちに、個人情報や決済情報が外部に流出する。
  • ソーシャルメディアの投稿を勝手に取得
  • メールの内容を読み取る
  • オンラインショッピングの履歴を盗む
  • シナリオ2: データの不正取得

同一オリジンポリシーの役割

こうした クロスサイトリクエストフォージェリ(CSRF) 的な攻撃を防ぐために、ブラウザは「同一オリジンポリシー(Same-Origin Policy)」というルールを守ります。

🛡️ 同一オリジンポリシー: 自分のオリジン以外に対しては勝手に通信しない

しかし困ることもある

しかし実際には、フロントエンド(https://myapp.com)とAPIサーバー(https://api.myapp.com)が別オリジンになるケースはよくあります。

このままでは正しい通信すらブロックされてしまう…。 そこで登場したのが CORS です。

💡 CORSの役割: サーバーが「このオリジンからのアクセスは安全です」とブラウザに伝える仕組み

3. CORSの仕組み

CORSは、サーバーが「このオリジンからのアクセスはOKですよ」とブラウザに伝える仕組みです。

基本的な流れ

  1. フロントエンドが別オリジンのAPIにリクエストを送信
  2. ブラウザが「この通信は安全?」とサーバーに確認
  3. サーバーが「このオリジンは許可します」と返答
  4. ブラウザが通信を許可

重要なHTTPヘッダー

そのための代表的なHTTPヘッダーがこちら:

http
Access-Control-Allow-Origin: https://myapp.com

これが返ってくれば、ブラウザは通信を許可します。 逆に書かれていなければ「CORSエラー」となります。

その他の重要なヘッダー

http
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 メソッド(特定の条件のみ)
  • 標準的なヘッダーのみ使用
  • プリフライト不要(シンプルリクエスト)

  • PUT DELETE など「副作用のある」メソッド
  • 独自ヘッダーを送る場合
  • Content-Type: application/json など
  • プリフライト必要(複雑なリクエスト)

プリフライトの流れ

このときブラウザは、まず以下のような OPTIONS リクエストをサーバーに送ります:

http
OPTIONS /api/data HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Content-Type

サーバーはこれに対して、

http
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:3000http://api.localhost:5000 この場合も別オリジン扱いとなり、CORSエラーが出ます。

  • 開発時はAPI側で Access-Control-Allow-Origin: * を一時的に許可
  • リバースプロキシを立てる
  • Next.jsのnext.config.jsでプロキシ設定
  • 解決策:

javascript
// 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ヘッダーを使う場合、追加設定が必要

必要な設定:

http
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属性との併用

http
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure
  • CORSでオリジンを制限
  • CSRFトークンでリクエストの正当性を確認
  • 二重のセキュリティ対策
  • CORSとCSRFトークンの組み合わせ

今後の展望

  • WebAssemblyとの連携強化
  • Service WorkerでのCORS制御
  • HTTP/3での最適化
🔮 将来性: CORSは今後もWebセキュリティの基盤として重要な役割を果たし続けます。

9. API設計での注意点

みなさんがAPIを設計・開発する際には、以下に注意してください:

セキュリティの原則

1. 許可するオリジンを最小限に

http
// ❌ 危険
Access-Control-Allow-Origin: *

// ✅ 安全
Access-Control-Allow-Origin: https://myapp.com

2. 必要なHTTPメソッドとヘッダーだけを許可

http
// ❌ 過度に広い許可
Access-Control-Allow-Methods: *

// ✅ 必要最小限
Access-Control-Allow-Methods: GET, POST

3. 認証が絡む場合は特に注意

http
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://myapp.com  // *は使えない

実装時のチェックリスト

  • [ ] 本番環境では * を使用していない
  • [ ] 必要なメソッドのみ許可している
  • [ ] 認証が必要な場合は credentials: true を設定
  • [ ] プリフライトリクエストに対応している
  • [ ] エラーハンドリングが適切に実装されている
🛡️ セキュリティファースト: 便利さよりも安全性を優先することが重要です。

まとめ

CORSとは何かを一言でまとめると、 「ブラウザがユーザーを守るために設けた"通信のルール"を、サーバーが許可する仕組み」 です。

この記事で学んだこと

  • オリジンとは何か(プロトコル・ドメイン・ポートの組み合わせ)
  • 同一オリジンポリシーがなぜ必要なのか(セキュリティ保護)
  • CORSでどのように制御しているのか(サーバー側の許可)
  • プリフライトリクエストの意味(事前確認)
  • 歴史的な背景と最新の状況(Ajax革命から現在まで)

実践的な理解

これらを理解しておけば、CORSエラーに出会っても「なるほど、サーバー側がこう返していないからだな」と冷静に判断できるでしょう。

重要なポイント

ネイティブアプリやサーバーサイドではCORSは基本的に関係ありません。これはあくまで「ブラウザの仕様」 だからです。

みなさんも次にCORSエラーを見かけたら、「ブラウザが安全確認をしてくれているんだ」と思い出してください。


最後に

CORSは複雑に見えますが、その背景には「ユーザーの安全を守る」という重要な目的があります。 適切に理解し、実装することで、安全で使いやすいWebアプリケーションを作ることができるのです。

💡 覚えておいてください: CORSエラーは「問題」ではなく、「ブラウザが正常に働いている証拠」です。

関連記事

2025年9月21日

APIキーの取り方からWeb実装まで — OpenAI / Claude(Anthropic) / Amazon Bedrockを“手を動かす人”向けにやさしく解説

生成AI APIを実務のWebアプリに安全に組み込むための実践ガイド。キーの取得、認証、最小コード例、料金の考え方、Next.jsでの安全な組み込みパターン、運用のコツまで網羅。

テクノロジー続きを読む
2025年9月9日

Next.js と Node.js――歴史の片鱗から最新活用まで

Next.js と Node.js の歴史から最新の活用方法まで、React 時代のフルスタック開発を段階的に解説。初心者でも理解できる実践的なガイドです。

テクノロジー続きを読む
2025年9月28日

OIDCって何?どう違う?なぜ"すごい"のか(AWS×GitHubの実例つき徹底講義)

OIDC(OpenID Connect)について、ゼロから体系的に学びます。OAuth2.0やSAMLとの違い、AWSとGitHubでの実装例まで、実例と図解で丁寧に解説します。

テクノロジー続きを読む
2025年9月10日

VPNとは何か?クラウド時代のVPN活用と中国での現状

VPNの基本からクラウドサービスでの活用、中国での特殊な状況まで、初心者にも分かりやすく解説します。セキュリティとプライバシーを守る技術の全体像を理解できます。

テクノロジー続きを読む
2025年10月1日

悪質なWeb広告の実態と被害を避けるための完全ガイド

恐怖を煽るウイルス警告やサブスク詐欺など悪質なWeb広告の手口・背景・対策を整理し、個人とサイト運営者が取るべき行動を解説します。

一般続きを読む