フォームとCSRF保護

1. Blade でフォームを構築する基本

要素 役割 Blade での記述例
<form> タグ 送信先 URL と HTTP メソッドを定義 <form method="POST" action="{{ route('posts.store') }}">
CSRF トークン Laravel が期待する _token フィールドを生成 @csrf
メソッドスプーフィング HTML がサポートしない PUT / PATCH / DELETE を疑似的に送信 @method('PUT')
  • Laravel ではフォームヘルパを必要とせず、純粋な HTMLBlade ディレクティブのみでフォームを組み立てられます。

  • 送信ボタンなど他の要素は通常の HTML と同様に配置します。

  • old('field') を使うとバリデーションエラー後に入力値を再表示できます。 laravel.comlaravel.com


2. CSRF(Cross-Site Request Forgery)保護の仕組み

  1. トークン発行

    • 初回リクエスト時、Laravel はセッションと紐付いた ランダムな CSRF トークン を生成し、レスポンスの Cookie(XSRF-TOKEN)とサーバ側セッションに保存します。

  2. フォーム埋め込み

    • Blade の @csrf が隠し入力 <input type="hidden" name="_token" value="…"> を生成し、上記トークンをフォーム内に埋め込みます。

  3. 検証

    • フォーム送信時、VerifyCsrfToken ミドルウェアが Cookie とフォーム値 を比較し、一致しない場合は 419(Page Expired)を返します。

    • トークンは POST・PUT・PATCH・DELETE リクエストで自動検証されます。 laravel.comlaravel.com


3. Laravel 11 での変更点

項目 Laravel 10 以前 Laravel 11 以降
ミドルウェアの場所 app/Http/Middleware/VerifyCsrfToken.php フレームワーク側に同梱(vendor 配下)
除外ルートの定義 ミドルウェアの $except 配列 bootstrap/app.phpcsrf.except 設定キーにパスを列挙
カスタムミドルウェア 既存ファイルを継承して差し替え 独自ミドルウェアを作成し、csrf.middleware 設定を上書き
  • アプリ側にミドルウェアが存在しない ため、CSRF を除外したいルートや SPA/API 用にカスタマイズする際は bootstrap/app.php に設定を追記します。

  • アップグレード時に「CSRF token mismatch」が多発する場合は、設定漏れやキャッシュを確認します。 stackoverflow.comlaracasts.com


4. JavaScript/Ajax と CSRF

シナリオ 推奨手順
Axios/Fetch window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name=\"csrf-token\"]').content;
Livewire, Inertia.js フレームワーク側で自動付与されるため追加不要
API(Bearer 認証) 通常は CSRF を無効化 し、代わりに Laravel Sanctum などのトークン認証を採用
  • @csrf ディレクティブは <meta name="csrf-token"> も併せて出力するため、フロントエンドからヘッダーに転用できます。 medium.com


5. CSRF 保護に関するベストプラクティス

  1. 常に @csrf を使用

    • 例外は GET リクエストのみ(状態を変えないため)。

  2. セッション有効期限と同時にトークンも期限切れ

    • 長時間フォームを開いたまま送信すると 419 エラーになり得るため、UX 改善にはフロント側リロードや自動トークン更新を検討。

  3. 例外ルートは最小限に

    • WebHook 受信など正当な理由がある場合だけ csrf.except へ追加。

  4. セキュリティヘッダ併用

    • SameSite=Lax/StrictContent-Security-Policy も合わせて設定すると総合的な CSRF 耐性が向上します。 dev.to


6. よくあるトラブルシューティング

症状 主な原因 対処
419 Page Expired フォームに _token が含まれていない @csrf の記述漏れを確認
Token Mismatch Cookie が更新され、古いフォームを送信 セッション期限を延長する/ページをリロード
SPA で 419 Axios にヘッダーが無い <meta name="csrf-token"> を読み込ませる
外部サービス POST 失敗 CSRF により拒否 csrf.except で該当パスを除外しつつ入力検証を強化

まとめ

  • @csrf はフォームに必須。Blade でワンライナー生成でき、メソッドスプーフィングと併用して RESTful ルートを安全に呼び出せます。

  • 検証は VerifyCsrfToken ミドルウェアが担い、Laravel 11 からはフレームワーク組込みで設定ファイル経由の管理へ変更されました。

  • Ajax / SPA でも X-CSRF-TOKEN ヘッダー を正しく送れば検証は通過します。API は CSRF を無効化してトークン認証(Sanctum 等)を利用するのが一般的です。

  • トークン不一致エラー時は Cookie, セッション, キャッシュ を順に確認し、ルート除外は最終手段と考えてください。

ChatGPT4o 生成日:2025/06/23