「パスワード忘れ」修正
All checks were successful
Deploy main / deploy (push) Successful in 23s

This commit is contained in:
OU.ZAIKOU 2026-01-29 00:02:45 +09:00
parent 8b42340915
commit 5df6c31b86
2 changed files with 87 additions and 6 deletions

View File

@ -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', [

View File

@ -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時間が切れました。再度お手続きを行ってください。']);
}
// パスワード更新