認証ミドルウェアやCORS対応

1. Laravelにおけるミドルウェアの位置づけ

  • HTTP リクエスト―レスポンスのライフサイクルを横断的にフックし、共通処理(認証・ログ・CORS など)を挿し込む仕組み

  • app/Http/Kernel.phpグローバル/ルートグループ/単一ルートの 3 段階で登録・適用順を制御

  • PSR-15 とは異なり、スタック方式(前後段で $next($request))で実装される


2. 認証ミドルウェア

ミドルウェア 目的 利用例 主な設定/拡張ポイント
auth セッション/トークンいずれも対応。指定ガードで未認証ならリダイレクト Route::middleware('auth')->group(...) config/auth.php でガード種別を定義
auth.basic HTTP Basic 認証を最小構成で提供 Route::get('/admin', fn() => ...) ->middleware('auth.basic') AUTH_USER ヘッダで簡易保護。本番では TLS 必須
auth:sanctum API トークン(Cookie / Bearer)認証 SPA⇔API を統合認証。Route::middleware('auth:sanctum')... EnsureFrontendRequestsAreStateful で SPA Cookie を許可
auth:api Laravel Passport / OAuth2 アクセストークン用 大規模 API でスコープ制御 config/passport.php, php artisan passport:install
カスタム 例)RoleMiddleware, AgeCheck Route::middleware(['auth', 'role:admin'])->... php artisan make:middleware RoleMiddleware で生成

実装のポイント

  1. 生成 php artisan make:middleware Authenticate(既定クラスは存在)

  2. ガード切替 ルート側で auth:guard名 を付与すると $this->auth->guard($name)->check() に自動反映

  3. 未認証時の戻り値 Web =リダイレクト、API = 401 JSON を使い分けるため、redirectTo() をオーバーライド

  4. 複数ミドルウェア Route::middleware(['auth','verified','throttle:60,1'])... のように 配列記法 で順番を保持

  5. テスト actingAs($user,'api') でガードを指定し、Feature Test で認証フローを検証


3. CORS 対応ミドルウェア

3-1. 基本構造

  • Laravel 7 以降は HandleCors を標準同梱(内部では fruitcake/laravel-cors コンポーネント)

  • 既定で api スタックに含まれ、SPA × API 構成で プリフライト OPTIONS を自動処理

3-2. 設定ファイル config/cors.php

キー 役割 よく使う設定例
paths 適用エンドポイント ['api/*', 'sanctum/csrf-cookie']
allowed_origins 許可ドメイン ['https://example.com'] or ['*']
allowed_methods 許可 HTTP メソッド ['GET','POST','PUT','DELETE','OPTIONS']
allowed_headers クライアント送信を許可するヘッダ ['Content-Type','Authorization','X-Requested-With']
supports_credentials Cookie 認証を許可するか true(Sanctum の SPA モードで必須)
max_age プリフライトのキャッシュ秒数 3600

Tip: .envCORS_ALLOWED_ORIGINS などを置き、環境別に動的読み込みすると運用が楽になります。

3-3. カスタマイズ例

php
// app/Http/Kernel.php protected $middleware = [ // ...既定 \App\Http\Middleware\TrustProxies::class, \Fruitcake\Cors\HandleCors::class, // グローバル適用 ]; // 追加の動的判定が必要な場合は独自ミドルウェアを挿む class DynamicCors { public function handle($request, Closure $next) { $origin = $request->headers->get('Origin'); if ($this->isTenantAllowed($origin)) { config(['cors.allowed_origins' => [$origin]]); } return $next($request); } }

3-4. テストとデバッグ

bash
# プリフライト curl -X OPTIONS https://api.example.com/resource \ -H "Origin: https://frontend.example.com" \ -H "Access-Control-Request-Method: GET" -i # → Access-Control-Allow-Origin: https://frontend.example.com が返ること
  • 順序依存: HandleCors最上段 あるいは 最下段 に置くと意図しないヘッダ上書きが防げる

  • キャッシュ: ブラウザは max_age 内でリクエストを省くため、設定変更後はキャッシュを削除する


4. ベストプラクティスまとめ

項目 推奨策
ガード設計 Web と API でガードを分離し、auth vs auth:sanctum の衝突を避ける
リダイレクト先 SPA で 401 JSON を返したい場合は Authenticate::$except ではなく redirectTo() を上書き
ミドルウェア順序 CORS → ProxyTrust → RateLimit → 認証 の順が典型
環境変数化 CORS 許可オリジン・トークンクッキー Domain は .env に持たせてデプロイ差分をなくす
テスト自動化 Feature Test で「認証成功/失敗」「CORS ヘッダ」をアサートしてリグレッションを防止
セキュリティ allowed_origins をワイルドカード * にしない。公開 API のみ限定的に許可範囲を広げる
バージョンアップ Laravel 11 以降は HandleCors がグローバル登録済み。果樹系パッケージは不要になったため、composer.json から削除しておく

まとめ

  • 認証ミドルウェアは ガード・トークン種別・リダイレクト挙動 を軸に設計・拡張する

  • CORS は HandleCorsconfig/cors.php で原則完結。SPA → API、モバイルアプリ → API 連携でもほぼ同じ構成で運用できる

  • 登録順序と環境ごとの設定切替 を押さえれば、セキュアかつメンテナブルなミドルウェア構成を構築できる

ChatGPT4o 生成日:2025/06/23