はじめに
「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)
以下の条件をすべて満たす場合は「シンプルリクエスト」として扱われます。
- メソッドが
GETPOSTHEADのいずれか - ヘッダーが
Content-Typeなど基本的なものだけ -
Content-Typeがapplication/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のセキュリティモデル全体への理解も深まります 🌐
ぜひ手を動かしながら試してみてください 💪
📚 参考・もっと深く学びたい方へ
💬 質問や感想があれば、コメント欄でお気軽にどうぞ!
👍 役に立ったら、いいね&ストックをお願いします!
🎓 ここまで読んでくださって、本当にありがとうございました!