LoginSignup
0
1

More than 1 year has passed since last update.

Laravelにおける2重サブミット防止

Posted at

初めに

私は、業務系のWebアプリケーションを作っているエンジニアです。

問合せでよくあるのが実行ボタン押しても、なかなか画面が変わらなくて、もう一度押したらエラーになりましたってやつ。
(なんで対策してないんだよ・・・)

てことで、Laravelにおける2重サブミット防止方法は以下の通りです。

2重サブミット対策

やることは2つ!

  • バックエンドで、リクエストを受けてからトークンを再生成させる。そうすると、レスポンスが返る前に再度サブミットされるとトークンミスマッチ(419:TokenMismatchException)になる。
  • フロントエンドで、ボタン押下後にボタンを非活性にする。

サーバーサイド

1. コントローラ

トークンを再生成した状態で、レスポンスが返る前に再度サブミットされるとトークンミスマッチが発生します。
※2〜3は、コード修正不要。

$session->regenerateToken();

2. ミドルウェア

トークンマッチをチェックする。
※標準で設定されてるので、追加は不要。

VerifyCsrfToken.php
public function handle($request, Closure $next)
    {
        if (
            $this->isReading($request) ||
            $this->runningUnitTests() ||
            $this->inExceptArray($request) ||
            $this->tokensMatch($request)
        ) {
            return tap($next($request), function ($response) use ($request) {
                if ($this->shouldAddXsrfTokenCookie()) {
                    $this->addCookieToResponse($request, $response);
                }
            });
        }

        throw new TokenMismatchException('CSRF token mismatch.');
    }

3. カーネル

ここで、ミドルウェアを設定することでリクエストの際に処理されるようになります。
※標準で設定されてるので、追加は不要。

Kernel.php
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

フロントエンド

ボタン押下時、ボタンを非活性にし、フォームを送信する。

<input type="button" id="btn1" value="実行">
$("#btn1").click(function() {
    $("#btn1").prop("disabled", true);
    $("form").submit();
});
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1