25.

Laravel の csrf_field の使い方

編集
この記事の要点
  • @csrf (旧 {{ csrf_field() }}) は Laravel フォームにCSRF トークンを埋め込む Blade ディレクティブ
  • POST/PUT/PATCH/DELETE 全てに必須(GET 不要)
  • トークンチェックは VerifyCsrfToken ミドルウェアが自動実行
  • Ajax の場合は X-CSRF-TOKEN ヘッダで送る
  • 除外したい URL は VerifyCsrfToken::$except 配列に追加

 

CSRF とは

CSRF (Cross-Site Request Forgery / クロスサイトリクエストフォージェリ) は、悪意あるサイトがユーザのブラウザを利用して別サイトに無断でリクエストを送る攻撃。

例: ユーザが銀行サイトにログイン中、攻撃者のサイトを開くと、JavaScript が銀行 API に送金リクエストを送る → ログインクッキーが付くので成功してしまう。

対策: フォーム送信時にサーバ側が発行した秘密のトークンを併送し、トークン一致を検証。

Laravel の CSRF トークン埋め込み

Blade テンプレート


@csrf
{{ csrf_field() }}

各 HTTP メソッド対応


@csrf ...
@csrf @method("PUT") ...
{{ csrf_field() }} {{ method_field("PUT") }}

Ajax / fetch / axios での CSRF トークン送信

方法 1: meta タグから読み取って X-CSRF-TOKEN ヘッダ





方法 2: フォームデータに含める

// FormData に含める
const formData = new FormData();
formData.append("_token", csrfToken);
formData.append("name", "Alice");
fetch("/users", { method: "POST", body: formData });

VerifyCsrfToken ミドルウェア

CSRF チェックは Laravel の web ミドルウェアグループに含まれる VerifyCsrfToken が自動で実行します:

// app/Http/Kernel.php
protected $middlewareGroups = [
    "web" => [
        // ...
        \App\Http\Middleware\VerifyCsrfToken::class,  // ← これ
        // ...
    ],
];

// 内部の動作:
// 1. POST/PUT/PATCH/DELETE リクエストを検出
// 2. _token フィールド or X-CSRF-TOKEN ヘッダから値を取得
// 3. セッション内のトークンと一致するか検証
// 4. 不一致なら 419 (Page Expired) エラー

419 Page Expired エラー

CSRF トークンが無効な時のエラー。原因:

  • @csrf / csrf_field() の付け忘れ: フォームに記述漏れ
  • セッション期限切れ: フォームを開いてから長時間経過
  • セッション cookie 設定ミス: SESSION_DOMAIN / SESSION_SECURE_COOKIE
  • キャッシュ問題: ブラウザ・CDN キャッシュで古いトークン使用
  • HTTPS 混在: HTTP と HTTPS のセッション分離

特定 URL を CSRF チェックから除外

外部 API からの Webhook 等、CSRF チェック不要な URL は除外可能:

// app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends Middleware
{
    protected $except = [
        "stripe/*",
        "webhook/*",
        "api/external/payment-callback",
    ];
}

注意: 除外した URL は CSRF 攻撃に晒されます。代わりに別の認証(API トークン、署名検証)を使うこと。

API(Sanctum / Passport)の場合

SPA + Sanctum の場合は別の仕組み:

// 初回: /sanctum/csrf-cookie で XSRF-TOKEN cookie 取得
await axios.get("/sanctum/csrf-cookie");

// 以降は cookie + X-XSRF-TOKEN ヘッダで認証
await axios.post("/api/users", data);
// axios は自動で XSRF-TOKEN cookie を X-XSRF-TOKEN ヘッダに変換

トークンの取得方法

// Controller / その他 PHP コードから
$token = csrf_token();

// Blade
{{ csrf_token() }}

// Session から直接
session()->token()

セキュリティのベストプラクティス

  • すべての POST/PUT/PATCH/DELETE に @csrf: 例外なし
  • session.same_site = lax: CSRF 防御の追加層(config/session.php)
  • HTTPS 必須: トークン盗聴防止
  • session expire 短め: 漏洩リスク軽減
  • Origin / Referer ヘッダ確認: 追加防御
  • SameSite=Strict: より厳格な防御(UX 影響あり)

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストールと設定
  2. クイックスタート & チュートリアル(初心者向け)
  3. クイックスタート & チュートリアル(中級者向け)
  4. ルーティング
  5. Bladeテンプレート(ビュー/レイアウト)
  6. コントローラー
  7. マイグレーションとテーブル定義
  8. データベースの設定
  9. Eloquentモデル (ORM)
  10. SQLとクエリビルダー
  11. バリデーション
  12. .envファイルの設定値へのアクセス
  13. 動作環境による分岐処理
  14. configフォルダ配下の設定値へのアクセス
  15. assetヘルパーを利用したpublicフォルダへのアクセス
  16. storageフォルダへのアクセス
  17. アプリケーション名の変更
  18. メンテナンス
  19. ログイン画面(認証システム)の作成
  20. ログインの必須化
  21. ログインユーザー情報の取得
  22. ルートの認証化
  23. 本番サーバーへのデプロイ方法
  24. 多言語化
  25. csrf_field
  26. ファイルのダウンロード
  27. CSVのアップロードおよび読み込み(maatwebsite/excel)
  28. ページタイトルの設定
  29. コマンド一覧
  30. エラー一覧
  31. SQLの実行ログ出力方法
  32. キャッシュのクリア
  33. Selectの結果の最初もしくは最後に任意の値を追加する方法
  34. ajaxでPOST通信する際の注意点
  35. ソーシャルログインの実装
  36. セッション情報の確認
  37. ログイン、ユーザー登録、パスワードリセット後のリダイレクト先の変更方法
  38. redirectやreturn viewにメッセージを付与する方法
  39. クッキー(cookie)の設定と取得
  40. クラスの再読み込み
  41. csrfの有効時間を変更する方法
  42. ViewComposerを用いてviewに共通の値を付与する方法
  43. View::shareを用いて共通の値を各ビューに渡す方法
  44. ミドルウェアを用いた処理の共通化
  45. Middleware内でAuth::check()などを使用する方法
  46. Controller以外でリダイレクトする方法
  47. セッションの値の取得/保存/更新/削除
  48. $requestの値を変更する方法
  49. 常時SSL化
  50. ページング(ページネーション)をする方法
  51. vue.jsとの連携
  52. Vue.jsと連携するSPA実行環境構築
  53. .envの値をvue.jsで参照する方法
  54. vue.jsを本番環境にリリースする方法
  55. could not find driver(Windows, MySQL編)