C
ネットワーク/セキュリティ/Lesson 07

CORS + セキュリティ — 同一オリジン・CORS・Preflight

30分·theory

CORS + セキュリティ — 同一オリジン・CORS・Preflight

🎯 このlessonを読み終えたら

このlessonを読み終えると、以下の3つを自信を持って実践できるようになります。

  • ✅ CORS preflight + Access-Control-Allow-Origin
  • ✅ XSS・CSRF・SQLインジェクション対策
  • ✅ helmet・CSP・HSTSセキュリティヘッダー

学習目標をチェックリストとして手元に置き、すべて答えられるようになったらlessonを閉じましょう。

Same-Origin Policy + CORS

Same-Origin Policy (SOP) — ブラウザセキュリティの基本

  • 同じオリジンのリソースのみJavaScriptからアクセス可能
  • オリジン (Origin) = プロトコル + ホスト + ポート
  • https://example.com:443 vs https://api.example.com:443 = 異なるオリジン

SOPがない場合

  • 悪意あるサイトが銀行のクッキーを使って送金リクエストを送信可能
  • 非常に危険 → ブラウザが強制的に制限

CORS (Cross-Origin Resource Sharing) — SOPの例外メカニズム:

  • サーバーがAccess-Control-Allow-Originヘッダーで許可するオリジンを明示
  • ブラウザが検証

Simple Request(CORS preflight不要):

  • メソッド:GET・HEAD・POSTのみ
  • ヘッダー:標準のみ(Content-Typeも制限あり)
  • Content-Type:text/plainapplication/x-www-form-urlencodedmultipart/form-dataのみ

違反時:ブラウザがレスポンスをJavaScriptからブロック。(リクエスト自体はサーバーに届く

CORS Preflight + 解決方法

Preflight Request危険なリクエストの前に行う事前確認:

条件(いずれか一つでも該当する場合にpreflightが発生):

  • メソッド:PUT・DELETE・PATCHなど
  • カスタムヘッダー:AuthorizationX-API-Key
  • Content-Type:application/json

Preflightの流れ

code
1. ブラウザ: OPTIONS /api/users
   Origin: https://frontend.com
   Access-Control-Request-Method: POST
   Access-Control-Request-Headers: Authorization, Content-Type

2. サーバー: 200 OK
   Access-Control-Allow-Origin: https://frontend.com
   Access-Control-Allow-Methods: POST, PUT, DELETE
   Access-Control-Allow-Headers: Authorization, Content-Type
   Access-Control-Max-Age: 600    (10分キャッシュ)

3. 実際のリクエスト: POST /api/users
4. 正常処理

サーバー側の解決策

Express

javascript
const cors = require('cors');
app.use(cors({
  origin: ['https://frontend.com', 'https://admin.example.com'],
  credentials: true,        // クッキーを許可
  methods: ['GET','POST','PUT','DELETE','PATCH'],
  allowedHeaders: ['Content-Type','Authorization'],
  maxAge: 600,
}));

Spring

java
@CrossOrigin(origins = "https://frontend.com",
             allowCredentials = "true")
@RestController
public class UserController { ... }

// またはグローバル:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
  @Override public void addCorsMappings(CorsRegistry r) {
    r.addMapping("/api/**")
     .allowedOrigins("https://frontend.com")
     .allowedMethods("GET","POST","PUT","DELETE")
     .allowCredentials(true);
  }
}

CORSによくある落とし穴

  • Access-Control-Allow-Origin: * + Allow-Credentials: true → 無効(セキュリティの矛盾)
  • ❌ ワイルドカード * はクッキーと併用不可
  • ❌ プロキシでCORSを回避(開発環境のみ — 本番環境では正式に設定すること)
  • ✅ 明示的なオリジンリスト + 資格情報の明示 + preflightのキャッシュ

プロキシ + セキュリティヘッダー

プロキシサーバー — クライアントとサーバーの間の仲介者

Forward Proxy(フォワードプロキシ):

  • クライアント
  • ユーザーIPを隠し、コンテンツフィルタリングを実施
  • 例:企業ファイアウォール・VPN・Squid

Reverse Proxy(リバースプロキシ):

  • サーバー
  • クライアントはプロキシのみを見て、実際のサーバーは隠蔽される
  • ロードバランシング・SSL終端・キャッシング・圧縮
  • 例:Nginx・HAProxy・Cloudflare・AWS ALB

Nginxリバースプロキシの例

nginx
server {
    listen 443 ssl;
    server_name codemaster40.com;

    ssl_certificate /etc/letsencrypt/live/codemaster40.com/fullchain.pem;

    location / {
        proxy_pass http://localhost:3000;       # Next.js
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /api {
        proxy_pass http://localhost:8080;       # Spring Boot
    }

    # Rate limit
    limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
}

必須セキュリティヘッダー

ヘッダー用途
Strict-Transport-SecurityHTTPSの強制(HSTS)
X-Frame-Options: DENYクリックジャッキング対策(iframe遮断)
X-Content-Type-Options: nosniffMIMEタイプスニッフィングの遮断
Content-Security-PolicyXSS・インジェクション対策
Referrer-PolicyRefererヘッダーの露出制御
Permissions-Policyカメラ・マイクなどの権限制御

Helmet(Node.js・Express):

javascript
const helmet = require('helmet');
app.use(helmet());   // 上記ヘッダーを自動設定

🤖 AIへのリクエスト例

このlessonの概念を理解すれば、AIに具体的な指示を出せるようになります。漠然とした「直してくれ」ではなく、語彙を持ったリクエスト — それがトークン節約の出発点です。

  • 「このExpressアプリにhelmet + CORSホワイトリスト + CSPヘッダーを追加して」
  • 「このコードをOWASP Top 10でチェックして強化して」

なぜこれがトークンを減らすのか

概念を知らないと、AIの回答を受け取っても「それは何ですか?」と再度聞き返すことになります。その「聞き返し」がトークンを消費します。概念を一度身に付けておけば、会話が一度で完結します。

CORS + セキュリティ — 同一オリジン・CORS・プリフライト - ネットワーク