This commit is contained in:
parent
8b42340915
commit
5df6c31b86
@ -8,6 +8,7 @@ use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
@ -38,14 +39,39 @@ class ForgotPasswordController extends Controller
|
||||
return back()->withErrors(['email' => '該当するユーザーが見つかりません。']);
|
||||
}
|
||||
|
||||
// 5分間隔のメール送信制限チェック(最新のトークンを対象)
|
||||
$lastToken = DB::table('password_reset_tokens')
|
||||
->where('ope_mail', $user->ope_mail)
|
||||
->orderByDesc('created_at')
|
||||
->first();
|
||||
if ($lastToken) {
|
||||
// タイムゾーンを明示的に指定(デフォルトはUTCで解析される可能性がある)
|
||||
$lastCreatedAt = Carbon::parse($lastToken->created_at, config('app.timezone'));
|
||||
$now = now();
|
||||
|
||||
// 経過秒数で判定
|
||||
$diffSeconds = $lastCreatedAt->diffInSeconds(now(), false);
|
||||
$limitSeconds = 5 * 60; // 5分
|
||||
if ($diffSeconds < $limitSeconds) {
|
||||
$remainSeconds = $limitSeconds - $diffSeconds;
|
||||
// 残り秒を「分」に変換:端数は切り上げ(例:1秒残りでも1分と表示)
|
||||
$waitMinutes = (int) ceil($remainSeconds / 60);
|
||||
return back()->withErrors([
|
||||
'email' => "パスワード再設定メールは5分以上の間隔を置いて送信してください。{$waitMinutes}分後に再度お試しください。"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// トークン生成
|
||||
$token = Str::random(60);
|
||||
// SHA256ハッシュで保存(セキュリティ向上)
|
||||
$tokenHash = hash('sha256', $token);
|
||||
|
||||
// トークン保存(既存レコードがあれば更新)
|
||||
DB::table('password_reset_tokens')->updateOrInsert(
|
||||
['ope_mail' => $user->ope_mail],
|
||||
[
|
||||
'token' => $token,
|
||||
'token' => $tokenHash,
|
||||
'created_at' => now(),
|
||||
]
|
||||
);
|
||||
@ -54,10 +80,24 @@ class ForgotPasswordController extends Controller
|
||||
try {
|
||||
$resetUrl = url('/reset-password?token=' . $token . '&email=' . urlencode($user->ope_mail));
|
||||
|
||||
Mail::raw("下記URLからパスワード再設定を行ってください。\n\n{$resetUrl}", function ($message) use ($user) {
|
||||
$body = $user->ope_name . " 様\n\n" .
|
||||
"So-Managerをご利用いただき、ありがとうございます。\n\n" .
|
||||
"本メールは、パスワード再設定のご依頼を受けてお送りしております。\n\n" .
|
||||
"以下のURLをクリックし、新しいパスワードを設定してください。\n\n" .
|
||||
$resetUrl . "\n\n" .
|
||||
"※このURLの有効期限は、24時間です。\n" .
|
||||
"※有効期限を過ぎた場合は、再度パスワード再設定手続きを行ってください。\n" .
|
||||
"※本メールにお心当たりがない場合は、本メールを破棄してください。\n\n" .
|
||||
"_________________________________\n" .
|
||||
"So-Manager サポートセンター\n" .
|
||||
"E-mail : support@so-manager.com\n" .
|
||||
"URL : https://www.so-manager.com/\n" .
|
||||
"_________________________________";
|
||||
|
||||
Mail::raw($body, function ($message) use ($user) {
|
||||
$message->to($user->ope_mail)
|
||||
->from(config('mail.from.address'), config('mail.from.name'))
|
||||
->subject('パスワード再設定のご案内');
|
||||
->subject('【【So-Manager】パスワード再設定のご案内】');
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('ForgotPassword mail send failed', [
|
||||
|
||||
@ -14,6 +14,33 @@ class ResetPasswordController extends Controller
|
||||
{
|
||||
$token = $request->query('token');
|
||||
$email = $request->query('email');
|
||||
|
||||
// トークンのハッシュ化
|
||||
$tokenHash = hash('sha256', $token);
|
||||
|
||||
// トークン・メール・24時間以内の有効性をチェック
|
||||
$record = DB::table('password_reset_tokens')
|
||||
->where('ope_mail', $email)
|
||||
->where('token', $tokenHash)
|
||||
->first();
|
||||
|
||||
if (!$record) {
|
||||
return redirect()->route('forgot_password')
|
||||
->withErrors(['email' => 'URLの有効期限(24時間)が切れました。再度お手続きを行ってください。']);
|
||||
}
|
||||
|
||||
// 24時間チェック
|
||||
$createdAt = \Carbon\Carbon::parse($record->created_at);
|
||||
if ($createdAt->addHours(24)->isPast()) {
|
||||
// 期限切れトークンを削除
|
||||
DB::table('password_reset_tokens')
|
||||
->where('ope_mail', $email)
|
||||
->delete();
|
||||
|
||||
return redirect()->route('forgot_password')
|
||||
->withErrors(['email' => 'URLの有効期限(24時間)が切れました。再度お手続きを行ってください。']);
|
||||
}
|
||||
|
||||
return view('auth.reset-password', compact('token', 'email'));
|
||||
}
|
||||
|
||||
@ -25,14 +52,28 @@ class ResetPasswordController extends Controller
|
||||
'password' => 'required|confirmed|min:8',
|
||||
]);
|
||||
|
||||
// トークンチェック
|
||||
// トークンのハッシュ化
|
||||
$tokenHash = hash('sha256', $request->token);
|
||||
|
||||
// トークン・メール・24時間以内の有効性をチェック
|
||||
$record = DB::table('password_reset_tokens')
|
||||
->where('ope_mail', $request->email)
|
||||
->where('token', $request->token)
|
||||
->where('token', $tokenHash)
|
||||
->first();
|
||||
|
||||
if (!$record) {
|
||||
return back()->withErrors(['email' => '無効なトークンまたはメールアドレスです。']);
|
||||
return back()->withErrors(['email' => 'URLの有効期限(24時間)が切れました。再度お手続きを行ってください。']);
|
||||
}
|
||||
|
||||
// 24時間チェック
|
||||
$createdAt = \Carbon\Carbon::parse($record->created_at);
|
||||
if ($createdAt->addHours(24)->isPast()) {
|
||||
// 期限切れトークンを削除
|
||||
DB::table('password_reset_tokens')
|
||||
->where('ope_mail', $request->email)
|
||||
->delete();
|
||||
|
||||
return back()->withErrors(['email' => 'URLの有効期限(24時間)が切れました。再度お手続きを行ってください。']);
|
||||
}
|
||||
|
||||
// パスワード更新
|
||||
|
||||
Loading…
Reference in New Issue
Block a user