Laravel 5.7 で二重送信対策

メモ:

フォームなどの更新が伴うようなページで、予期しない複数回のリクエストに対応するよう Laravel 5.7 で対策を行ってみます。

二重送信などの複数回リクエスト対策

重複したリクエストが発生するケースとして、次のものが考えられます。

  • サブミットボタンをダブルクリックする。
  • 戻るボタンで戻って、再度サブミットボタンを押す。
  • 完了ページでリロードする。
  • CSRF攻撃によるリクエスト。

Laravel では、クロス・サイト・リクエスト・フォージェリ( CSRF )対策を行わないと 419 エラーが返されます。この対策に使用されているトークンを利用することで二重送信の対策を行います。

<?php

namespace App\Http\Controllers;

use App\Mail\Contact;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Http\Requests\ContactRequest;

class ContactController extends Controller
{
    //
    public function send(Request $request){

        $contact = $request->all();

        Mail::to('hogehoge@gmail.com')->send(new Contact($contact));

        // 二重送信対策
        $request->session()->regenerateToken();

        return 'メッセージを送信しました。';
    }
}

Laravel では、VerifyCsrfToken ミドルウェアがリクエスト中のトークンとセッションに保存されているトークンが一致するか確認するので、処理が完了した時点でトークンを再生成します。これにより重複したリクエストが発生した場合、トークンが一致しなくなりエラーとして処理されます。

トークンを再生成している部分は次のようになります。

// 二重送信対策
$request->session()->regenerateToken();

戻るボタンで戻って、再度サブミットボタンを押してみると 419 エラーが返され二重で送信されないことを確認できます。