Laravel 今更ながら(今後も見据えた) CSRF チェックの外し方
前書き
「オイオイ、今更かよ…」と思われそうですが、今回はこれを見て行きたいと思います。新鮮味が無いと面白くありませんので、後半の方では、まだリリースされていない Laravel Ver.11 情報と絡めて行きたいと思います。
本題
という事で、Laravel での CSRF トークンチェックの外し方を3選、ガッと書いてみたいと思います。もちろん普段は、CSRF トークンチェックは外すべきではありませんが、「外部との連携でここだけちょっと外したい」、という状況を想定しています。
その1、VerifyCsrfToken ミドルウェアの $except プロパティに URL を列挙する。
よくあるやり方ですね。ドキュメントにも書かれています。
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
protected $except = [
'payment/*',
];
}
手軽と言えば、手軽です。
その2、web.php ではなく、api.php の方に書く
web.php ではなく、api.php の方に書けば、最初から CSRF トークンチェックはありませんから、api.php に書くのが妥当な時は、いい選択肢ですね。
とは言え、api.php にはルートが1本だけで、他は全部 web.php に書かれている時は、孤島的な感じでちょっと微妙にもなったり。
その3、web.php にてミドルウェアを外す。
個人的にはちょっと本命で、下記みたいな感じです。
use App\Http\Middleware\VerifyCsrfToken;
Route::post('payment', PaymentController::class)
->withoutMiddleware(VerifyCsrfToken::class);
もしグループ化する際は、->group() より前に書いて、
Route::prex('payment')
->withoutMiddleware([VerifyCsrfToken::class])
->group(function () {
// ...
});
とこんな感じです。auth
とかのようにニックネームは無いので、クラスのフルパスを指定します。
これのメリットは、その1のやり方の場合、URL が変更になった際、$except プロパティの値も変更しないといけないのに対し(← 変更を忘れたりもして…)、こちらの書き方であれば、その心配は要らない事ですね。😊
Laravel Ver.11 では、上記はどうなる?
Laravel Ver.11 は、執筆時点でまだリリースされていませんので、以降は、その後変更無くリリースされたという前提での話になります。
(以降、Laravel Ver.11 を新規でインストールした場合の話です)
まず、デフォルトで、App\Http\Middleware\VerifyCsrfToken
のファイルが無くなります。(正確には、他にも色々無くなります)まぁ、無くなるというか、フレームワーク本体側に引っ越したという感じですね。
ですので、上記で見たその1のやり方をするのは、何か小面倒になりそうですね。
その2のやり方は、まぁ、特に変化ないでしょう。
その3のやり方は、App\Http\Middleware\VerifyCsrfToken
が無くなる為、フレームワーク側のクラスを指定します。
下記みたいな感じです。(実際は違う💢)
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
Route::post('payment', PaymentController::class)
->withoutMiddleware(VerifyCsrfToken::class);
これで大丈夫だろうと思いきや、全く動作しませんでした。😂
「オイオイ、エラーも出ないんだけど」と思っていたら、正解はこうでした。
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
Route::post('payment', PaymentController::class)
->withoutMiddleware(ValidateCsrfToken::class);
VerifyCsrfToken
→ ValidateCsrfToken
VerifyCsrfToken
はそのまま存在しつつ、影武者的な ValidateCsrfToken
ができていて、フレームワーク側では、ValidateCsrfToken
で指定されているので、ValidateCsrfToken
の方を指定して外してやります。
「いや、名前変えなくてもいいじゃん」と思ったりするのですが、Talor 氏的には、「consistency(一貫性)」の為の変更だそうです。(他の ValidateSignature、ValidatePostSize と名前を合わせたかったらしい)
余談ですが、Laravel にプルリク送る時は、「これは一貫性の為だ」とか、「Ruby on Rails でもこうなっている」とか添えると、マージ率が格段と上がります。筆者調べ(笑
雑感
Laravel Ver.11 では、特にスケルトン(土台)側のファイルが、デフォルトでかなり整理されている感じになりますね。という事で、今までのやり方を Laravel Ver.11 ではどんな風に書くのか色々調べています。
間違い等ありましたらコメント下さい。
Discussion
$except に生のパス書くの嫌で VerifyCsrfToken のコンストラクタに
とか書いてたんですが、ルートからミドルウェアを外す方法良いですね。
なるほど。コンストラクタを使うという手もあったのですね…。
1箇所で集中管理できるのはいいですね。
勉強になります❗😊