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: 悪意あるサイトからの攻撃

    1. 悪意あるサイトにアクセスしたユーザーのブラウザが、自動的にユーザーの銀行サイトへリクエストを飛ばす。

    → ユーザーがログイン済みなら、そのCookie情報が勝手に送信されてしまう。

    2. ユーザーが気づかないうちに、個人情報や決済情報が外部に流出する。

    シナリオ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ヘッダーがこちら:

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

  • PUT DELETE など「副作用のある」メソッド
  • 独自ヘッダーを送る場合
  • 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と連携するのが難しく、開発者は次のような工夫をしていました:

    当時の迂回策

    JSONP(JSON with Padding)

  • scriptタグ経由でデータ取得
  • セキュリティリスクが高い
  • エラーハンドリングが困難
  • リバースプロキシ

  • 自前サーバーを経由させる
  • サーバーリソースを消費
  • 設定が複雑
  • CORSの誕生

    こうした迂回策の不便さを解消するために、CORSが導入されたのです。

    📅 歴史的意義: CORSにより、Webアプリケーションの可能性が大幅に広がりました。


    6. よくある開発現場でのつまずき

    ケース1:ローカル環境でのテスト

    問題: http://localhost:3000http://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エラーは「問題」ではなく、「ブラウザが正常に働いている証拠」です。

    タグ:
    CORSフロントエンドWeb開発セキュリティAPIJavaScript