CSRF 保護

リクエストの作成

Laravel は、Inertia や Axios を介してリクエストを行う際に、適切な CSRF トークンを自動的に含めます。ただし、Laravel を使用している場合は、プロジェクトから csrf-token の meta タグを必ず削除してください。これが存在すると、CSRF トークンが正しく更新されなくなります。

サーバーサイドのフレームワークにクロスサイトリクエストフォージェリ(CSRF)保護が含まれている場合、POSTPUTPATCHDELETE リクエストに対して、各 Inertia リクエストに必要な CSRF トークンが含まれていることを確認する必要があります。

もちろん、すでに説明したとおり、Laravel などの一部のサーバーサイドフレームワークでは、リクエスト時に CSRF トークンの追加が自動的に処理されます。そのため、これらのフレームワークを使用している場合、追加の設定は不要です。

しかし、CSRF 保護を手動で処理する必要がある場合の一つの方法は、すべてのレスポンスに CSRF トークンを props として含めることです。その後、Inertia リクエストを行う際にそのトークンを使用できます。

また、Inertia の 共有データ 機能を使用して、各レスポンスに csrf_token を自動的に含めることもできます。

しかし、より良い方法は、Inertia が内部で使用している HTTP ライブラリである axios に組み込まれている CSRF 機能を利用することです。

Axios は XSRF-TOKEN クッキーの存在を自動的に確認します。これが存在する場合、Axios はリクエスト時に X-XSRF-TOKEN ヘッダーにトークンを含めます。

これを実装する最も簡単な方法は、サーバーサイドのミドルウェアを使用することです。各レスポンスに XSRF-TOKEN クッキーを含め、Axios から送信されるリクエスト内の X-XSRF-TOKEN ヘッダーを使用してトークンを検証するだけです。

不一致の処理

CSRF トークンの不一致が発生すると、サーバーサイドのフレームワークは通常、エラーレスポンスを返す例外をスローします。たとえば Laravel を使用している場合、TokenMismatchException がスローされ、419 エラーページが表示されます。これは有効な Inertia レスポンスではないため、エラーはモーダルで表示されます。

明らかに、これは良いユーザー体験とは言えません。より良い対処法は、ページの有効期限が切れたことを示すフラッシュメッセージとともに、直前のページへリダイレクトを返すことです。これにより、有効な Inertia レスポンスが返され、フラッシュメッセージが props として利用可能になり、ユーザーに表示できます。もちろん、これを機能させるには、Inertia と フラッシュメッセージ を共有する必要があります。

Laravel を使用している場合、アプリケーションの例外ハンドラを変更して、ユーザーを直前に表示していたページへ自動的にリダイレクトし、同時にセッションへメッセージをフラッシュすることができます。これを実現するには、アプリケーションの bootstrap/app.php ファイル内で respond 例外メソッドを使用します。

php
use Symfony\Component\HttpFoundation\Response;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->respond(function (Response $response) {
        if ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'ページの有効期限が切れました。もう一度お試しください。',
            ]);
        }

        return $response;
    });
});

最終的に、これはユーザーにとってはるかに良い体験となります。エラーモーダルが表示される代わりに、ページの有効期限が「切れた」ことを示すメッセージが表示され、再試行するよう促されます。