前提
Laravel5.7を使用して学習のため自作でログイン機能などを作成しております。
ですのでmake:authは使っていません。
パスワードを忘れてしまったユーザーに対して登録したメールアドレスを入力してもらう事で
パスワード再設定のご案内メールを送るページでの質問です。
実現したいこと
送信ボタンの連打、またはブラウザバックによるメールの多重送信を防ぎたい。
発生している問題
$request->session()->regenerateToken();
上記を使えば重複したリクエストが発生した場合、
リクエスト中のトークン($request->_token)と
セッションに保存されているトークン($request->session()->token())が
一致しなくなりエラーが返され多重で送信されないという事まで調べてわかりました。
(違っていたらご指摘お願い致します)
しかし私のコードでは連打すると1通目と2通目のセッション、トークン共に全て値が同じで
ブラウザバックすると1通目と2通目の値は違うもののセッションとトークンは一致しており多重送信されてしまいます。
何が間違っているのかわからない為ご教授頂けたらと思います。
補足
今回はセッションとトークンの値を簡単に確認するために
メールの件名にセッション、内容にトークンを入れています。
該当のソースコード
view
1@extends('layouts.default') 2 3 4@section('content') 5<div class="container mt-5"> 6 <div class="row justify-content-center"> 7 <div class="col-md-8"> 8 <div class="card"> 9 <div class="card-header">{{'パスワードの再設定申請'}}</div> 10 <div class="card-body"> 11 <p>登録されているメールアドレスを入力し、送信ボタンを押して下さい。</p> 12 <form method="POST" action="{{ url('/auth/password/forgot') }}"> 13 @csrf 14 <div class="form-group row"> 15 <label for="email" class="col-md-4 col-form-label text-md-right">{{'メール'}}</label> 16 <div class="col-md-6"> 17 <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required maxlength="100" autofocus> 18 @if ($errors->has('email')) 19 <span class="invalid-feedback" role="alert"> 20 <strong>{{ $errors->first('email') }}</strong> 21 </span> 22 @endif 23 @if (isset($message)) 24 <span class="invalid-feedback" role="alert"> 25 <strong>{{ $message }}</strong> 26 </span> 27 @endif 28 </div> 29 </div> 30 <div class="form-group row mb-0"> 31 <div class="col-md-8 offset-md-4"> 32 <button type="submit" class="btn btn-primary"> 33 {{'送信'}} 34 </button> 35 </div> 36 </div> 37 </form> 38 </div> 39 </div> 40 </div> 41 </div> 42</div> 43@endsection 44
controller
1public function sendForgetMail(Request $request) 2 { 3 $request->validate([ 4 'email' => 'required|string|email|max:100|exists:users,email', 5 ]); 6 $user = UsersTable::getUserData($request->email); 7 // トークン作成 8 $token = Common::createToken($request->email); 9 // URLの作成 10 $url = Common::fetchUrlForMail('auth/password/reset', $token); 11 // パスワードリセットテーブルに保存 12 TokensTable::insertPassToken($user->id, $token); 13 14 // メール送信 15 $mailer = new Mailer(); 16 //$mailer->sendMail($url, $request->email, 'パスワード再設定のご案内', 'emails.templates.password_reset_mail'); 17 $mailer->sendMail($request->_token, $request->email, $request->session()->token(), 'emails.templates.password_reset_mail'); 18 // 二重送信対策 19 $request->session()->regenerateToken(); 20 21 // 送信完了メッセージ 22 return view('auth.password.request_result'); 23 }