この記事は私が Laravel でアプリケーションを作り始めたときにいきなり躓きすぐさま解決したけれど、なんらかのバッドノウハウで回避しちゃってる方に贈ります。
※この記事は Laravel 6.0 を前提としています。
API のルーティングであなたはこんな経験はありませんか?
- rotes/api.php にルートを追加したのに呼び出せない(404になる)。
- REST API を外部から POST で呼び出したときに「419 Page Expired」というエラーが帰ってくる。
2については、調べてみるとどうやらリクエストに CSRFトークンが含まれていないといけないエラーである模様。結果、POST をあきらめて GET にしてみると、URL が長くなりすぎてエラーとなり、袋小路に迷い込んだ気分。
これは、私が Laravel で実際のアプリケーションを作り出して1日目に経験したことです。
ググって Stack Overlow を次々読むという不毛な作業をしたりもしたわけですけれど、あなたはそんなことをする必要はありません。
結論
rotes/api.php に追加したルートは URL に /api を追加したら呼び出せますし、 CSRF のチェックも回避できます。
もちろん、POSTということは何らかのデータを送信したいわけで、何のチェックもなくどこからもデータ受け入れ放題とはいきません。
送信元 IP アドレスをチェックする、HTTPヘッダに特定のフィールドを含ませチェックする、など middleware を追加して不正アクセス対策を実施ください。
ほんとうにもう以上なんですが、余談的にどうして api では CSRF が回避されるのか見てみましょう。
余談
Web Routes
rotes/web.php には、このように書かれています。
These routes are loaded by the RouteServiceProvider within a group which contains the “web” middleware group.
Web ルートは “web” ミドルウェアグループに属します。
ミドルウェアグループ は app/Http/Kernel.php に、以下のように定義されています。
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ 'throttle:60,1', 'bindings', ], ];
web グループの中に VerifyCsrfToken::class がありますね。
この指定があるため、 rotes/web.php に追加したルートではデフォルトで CSRF のチェックが有効になります。
API Routes
そのすぐ下に API のミドルウェアグループがありますが・・・throttle・・・これは何でしょうね?
以下のURLに詳細が書かれています。
Laravel 6.x ルーティング レート制限
throttle
ミドルウェアは分数と、その時間内に許す最大リクエスト数の、2引数を取ります。
つまり、'throttle:60,1',
という記述は、1分間に60回のアクセスが許されるということです。
これがデフォルトになっています。
もうひとつの bindings ・・・これもちょっと意味が分かりません。
web ルートの方にも SubstituteBindings というクラスがありますが、関係あるんでしょうか。
いろいろ検索した結果、以下のような記述がありました。
Once this route middleware has been registered, you should add it to the
https://laravel.com/docs/5.3/upgradeapi
middleware group:
1回登録したら次からは名前だけで OK と言いたいのでしょうか。
じゃぁ、throttle は引数まで引き連れて、こんなところで何してるんでしょうか。
そんなことはどうでもよくて、bindings は SubstituteBindings::class な模様。
そしてこの middleware は何をしてくれるのか。
ソースを見ても何も書いておらずここで力尽きたので、「WebルートとAPIルートでは常に使うんだな」と理解することにしました。
このミドルウェアが実現している Route Model Binding は以下のページが詳しいです。