0
0

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ってなに?オリジンから丁寧に解説【初心者向け完全ガイド】

0
Posted at

はじめに

「CORSエラーが出た!なんで?」
はじめてWeb開発を行うとよくぶつかるこの壁。
この記事では オリジン・IPアドレス・同一オリジンポリシー の基礎からやさしく解説します 🚀


🗺️ 全体の流れ(まずはざっくり!)

🌍 インターネットの仕組み
  ↓
1. IPアドレスとは?
  ↓
2. URLとオリジンとは?
  ↓
3. 同一オリジンポリシー(SOP)とは?
  ↓
4. CORSとは?なぜ必要?
  ↓
5. CORSの動作の仕組み(プリフライトリクエスト)
  ↓
6. CORSエラーの原因と解決方法

1️⃣ IPアドレスとは?

インターネット上の「住所」です。

人間の世界に住所(〇〇県〇〇市...)があるように、インターネット上のすべての機器には IPアドレス という識別番号が割り当てられています。

📮 IPv4アドレス(よく見る形式)

192.168.1.1
↑
0〜255の数値を4つ、ドット(.)でつなげた形式
種類 用途
プライベートIP 192.168.1.1 家庭内・社内LANなど
パブリックIP 203.0.113.5 インターネット上で公開
ループバックIP 127.0.0.1 自分自身を指す(localhost)

🌐 IPv6アドレス(最新形式)

2001:0db8:85a3:0000:0000:8a2e:0370:7334

IPv4のアドレス数(約43億個)が枯渇しつつあるため、より多くのアドレスを扱えるIPv6が普及中です。

🔤 ドメイン名とDNS

IPアドレスは数字の羅列で覚えにくいため、人間向けに ドメイン名 が使われます。

203.0.113.5  ←→  example.com
     ↑ この変換をしてくれるのが DNS(ドメインネームシステム)

💡 ポイント:ブラウザに google.com と入力すると、まずDNSに問い合わせてIPアドレスを取得し、そのIPアドレスに接続しています!


2️⃣ URLとオリジンとは?

🔗 URLの構造

https://www.example.com:443/path/to/page?query=1#section
  ↑          ↑            ↑      ↑            ↑       ↑
スキーム   ホスト名      ポート  パス         クエリ  フラグメント
(プロトコル)

🏠 オリジン(Origin)とは?

オリジン = スキーム + ホスト名 + ポート番号 の組み合わせです。

https://www.example.com:443
  ↑            ↑          ↑
スキーム    ホスト名    ポート番号

オリジンの比較例

URL オリジン 同一オリジン?
https://example.com/page1 https://example.com ✅ 基準
https://example.com/page2 https://example.com ✅ 同じ(パスが違うだけ)
http://example.com http://example.com ❌ 違う(スキーム[http]が違う)
https://sub.example.com https://sub.example.com ❌ 違う(ホストが違う)
https://example.com:8080 https://example.com:8080 ❌ 違う(ポートが違う)
https://other.com https://other.com ❌ 違う(ドメインが違う)

💡 ポイント:スキーム・ホスト・ポートが すべて一致 して初めて「同一オリジン」です!


3️⃣ 同一オリジンポリシー(SOP)とは?

🔒 同一オリジンポリシー(Same-Origin Policy)

ブラウザに組み込まれたセキュリティの基本ルールです。

「あるオリジンのWebページは、別のオリジンのリソースに自由にアクセスできない」

https://my-site.com のJavaScript
    ↓
❌ https://api.other.com へのリクエスト → ブロック!
✅ https://my-site.com へのリクエスト → OK!

🤔 なぜこのルールが必要?

悪意のあるサイトからの攻撃(例:CSRF)を防ぐためです。

😈 SOPがなかった場合の危険な例

1. ユーザーが banking.com にログイン(セッションCookieが保存される)
2. ユーザーが evil.com を開く
3. evil.com のJavaScriptが banking.com のAPIを勝手に叩く!
4. 送金・個人情報の取得などが可能になってしまう...😱

SOPがあることで、evil.com からの banking.com へのリクエストはブロックされます 🛡️


4️⃣ CORSとは?なぜ必要?

🌉 CORS(Cross-Origin Resource Sharing)

異なるオリジン間でのリソース共有を、安全に許可する仕組みです。

SOPは安全ですが、厳しすぎると困る場面があります。

😓 SOPが厳しすぎる例

フロントエンド: https://myapp.com
バックエンドAPI: https://api.myapp.com  ← サブドメインが違う!

→ SOPのせいでAPIにアクセスできない...

このような正当なクロスオリジン通信を安全に許可するのがCORSです。

🔑 CORSの基本的な考え方

ブラウザ → サーバーに「このオリジンからアクセスしてもいい?」と確認
サーバー → 「このオリジンはOK!」とレスポンスヘッダーで返答
ブラウザ → 許可されていれば通信を続ける

CORSはあくまで サーバー側が「許可」を出す 仕組みです。ブラウザがそれを確認します。


5️⃣ CORSの動作の仕組み

CORSには2つのリクエストパターンがあります。

📬 シンプルリクエスト(Simple Request)

以下の条件をすべて満たす場合は「シンプルリクエスト」として扱われます。

  • メソッドが GET POST HEAD のいずれか
  • ヘッダーが Content-Type など基本的なものだけ
  • Content-Typeapplication/x-www-form-urlencoded / multipart/form-data / text/plain のいずれか
1. ブラウザ → サーバーにリクエスト送信(Originヘッダー付き)
2. サーバー → レスポンスに Access-Control-Allow-Origin ヘッダーを付けて返す
3. ブラウザ → ヘッダーを確認してOKなら結果をJSに渡す
// リクエスト
GET /api/data HTTP/1.1
Origin: https://myapp.com

// レスポンス
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com  ← これがCORSの許可!

✈️ プリフライトリクエスト(Preflight Request)

シンプルリクエストの条件を満たさない場合(PUT DELETE application/json など)は、本番リクエストの前に「事前確認」 が行われます。これが プリフライト(Preflight) です。

【ステップ1】プリフライトリクエスト(OPTIONSメソッド)

ブラウザ ──── OPTIONS /api/data ────→ サーバー
              Origin: https://myapp.com
              Access-Control-Request-Method: POST
              Access-Control-Request-Headers: Content-Type

サーバー ────────── レスポンス ────────→ ブラウザ
              Access-Control-Allow-Origin: https://myapp.com
              Access-Control-Allow-Methods: POST, GET
              Access-Control-Allow-Headers: Content-Type

【ステップ2】本番リクエスト(許可された場合のみ)

ブラウザ ──── POST /api/data ─────────→ サーバー
              (実際のデータ送信)

💡 ポイント:プリフライトは「入店前にドレスコードを確認するようなもの」です!


📋 CORSで使われる主なHTTPヘッダー

リクエスト側(ブラウザが自動で付与)

ヘッダー 説明
Origin リクエスト元のオリジン
Access-Control-Request-Method 使いたいHTTPメソッド
Access-Control-Request-Headers 使いたいカスタムヘッダー

レスポンス側(サーバーが設定する)

ヘッダー 説明
Access-Control-Allow-Origin 許可するオリジン https://myapp.com or *
Access-Control-Allow-Methods 許可するHTTPメソッド GET, POST, PUT, DELETE
Access-Control-Allow-Headers 許可するヘッダー Content-Type, Authorization
Access-Control-Allow-Credentials Cookie送信を許可するか true
Access-Control-Max-Age プリフライト結果のキャッシュ時間(秒) 86400

6️⃣ CORSエラーの原因と解決方法

🚨 よくあるCORSエラーメッセージ

Access to fetch at 'https://api.example.com' from origin
'https://myapp.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on
the requested resource.

🔍 原因と対処法

❌ 原因1:サーバーにCORS設定がない

// NG: レスポンスヘッダーに Access-Control-Allow-Origin がない
HTTP/1.1 200 OK
Content-Type: application/json
// OK: ヘッダーを追加する
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: https://myapp.com  ✅

❌ 原因2:オリジンが一致していない

// 許可設定
Access-Control-Allow-Origin: https://myapp.com

// NG: 別オリジンからのリクエスト
Origin: https://other-site.com  → ❌ ブロック

❌ 原因3:credentials: true なのに * を使っている

// NG: Cookie送信を許可したいのに * は使えない
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true  → ❌ エラー

// OK: 具体的なオリジンを指定する
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Credentials: true  → ✅

🛠️ サーバー別のCORS設定方法

Node.js(Express)

const express = require('express');
const cors = require('cors');
const app = express();

// すべてのオリジンを許可(開発環境向け)
app.use(cors());

// 特定のオリジンだけ許可(本番環境向け)
app.use(cors({
  origin: 'https://myapp.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

Python(FastAPI)

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://myapp.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Nginx(リバースプロキシ)

location /api/ {
    add_header Access-Control-Allow-Origin "https://myapp.com";
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization";

    if ($request_method = OPTIONS) {
        return 204;
    }
}

🔄 全体まとめ

ステップ 内容
1️⃣ IPアドレス = インターネット上の住所。ドメイン名はDNSでIPに変換される
2️⃣ オリジン = スキーム+ホスト+ポートの組み合わせ
3️⃣ 同一オリジンポリシー(SOP)= 異なるオリジンへのアクセスをブラウザがブロック
4️⃣ CORS = SOPを安全に緩和して、クロスオリジン通信を許可する仕組み
5️⃣ プリフライトリクエスト = 本番リクエスト前にOPTIONSで事前確認
6️⃣ CORSエラーはサーバー側のレスポンスヘッダー設定で解決できる

⚠️ よくある誤解

❌ 「CORSはサーバーを守る仕組み」
✅ 「CORSはブラウザ上のJavaScriptを守る仕組み」

→ curlやPostmanからはCORSの制限を受けません。
  あくまでブラウザが行うチェックです!
❌ 「Access-Control-Allow-Origin: * にすれば全部解決!」
✅ 「* はCredentials(Cookie)と組み合わせられないし、セキュリティリスクあり」

→ 本番環境では必ず許可するオリジンを明示しましょう。

🎓 まとめ

  • IPアドレス はインターネット上の住所、ドメイン はその人間向けの名前
  • オリジン = スキーム+ホスト+ポートの三点セット
  • SOP(同一オリジンポリシー) はブラウザのセキュリティの基本ルール
  • CORS はSOPを安全に緩和するためのHTTPヘッダーを使った仕組み
  • CORSエラーの解決は サーバー側のレスポンスヘッダー設定 が鍵!

CORSを理解すれば、Webのセキュリティモデル全体への理解も深まります 🌐
ぜひ手を動かしながら試してみてください 💪

📚 参考・もっと深く学びたい方へ

💬 質問や感想があれば、コメント欄でお気軽にどうぞ!
👍 役に立ったら、いいね&ストックをお願いします!
🎓 ここまで読んでくださって、本当にありがとうございました!

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?