diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 9afd5ff4..6e1ac4ed 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -152,8 +152,18 @@ class AuthController extends Controller return json(trans('auth.forgot.disabled'), 1); } - if (Session::has('last_mail_time') && (time() - session('last_mail_time')) < 60) - return json(trans('auth.forgot.frequent-mail'), 1); + $rateLimit = 180; + $lastMailCacheKey = sha1('last_mail_'.Utils::getClientIp()); + $remain = $rateLimit + Cache::get($lastMailCacheKey, 0) - time(); + + // Rate limit + if ($remain > 0) { + return json([ + 'errno' => 2, + 'msg' => trans('auth.forgot.frequent-mail'), + 'remain' => $remain + ]); + } // Get user instance $user = $users->get($request->input('email'), 'email'); @@ -171,7 +181,7 @@ class AuthController extends Controller return json(trans('auth.forgot.failed', ['msg' => $e->getMessage()]), 2); } - Session::put('last_mail_time', time()); + Cache::put($lastMailCacheKey, time(), 60); return json(trans('auth.forgot.success'), 0); } diff --git a/resources/lang/en/auth.yml b/resources/lang/en/auth.yml index 7b5e1782..ed5dd246 100644 --- a/resources/lang/en/auth.yml +++ b/resources/lang/en/auth.yml @@ -28,7 +28,7 @@ forgot: message: We will send you an E-mail to verify. login-link: I do remember it disabled: Password resetting is not available. - frequent-mail: You click the send button too fast. Wait for 60 secs, guy. + frequent-mail: You click the send button too fast. Wait for some minutes, guy. unregistered: The email address is not registered. success: Mail is sent. Will be expired in 1 hour, please check. failed: Fail to send mail, detailed message :msg diff --git a/resources/lang/zh_CN/auth.yml b/resources/lang/zh_CN/auth.yml index 8cd8b62b..9b071eb9 100644 --- a/resources/lang/zh_CN/auth.yml +++ b/resources/lang/zh_CN/auth.yml @@ -28,7 +28,7 @@ forgot: message: 我们将会向您发送一封验证邮件 login-link: 我又想起来了 disabled: 本站已关闭重置密码功能 - frequent-mail: 你邮件发送得太频繁啦,过 60 秒后再点发送吧 + frequent-mail: 你邮件发送得太频繁啦,过会儿再点发送吧 unregistered: 该邮箱尚未注册 success: 邮件已发送,一小时内有效,请注意查收。 failed: 邮件发送失败,详细信息::msg diff --git a/tests/AuthControllerTest.php b/tests/AuthControllerTest.php index 2bfc0870..16593d64 100644 --- a/tests/AuthControllerTest.php +++ b/tests/AuthControllerTest.php @@ -394,16 +394,21 @@ class AuthControllerTest extends TestCase ]); config(['mail.driver' => 'smtp']); + $lastMailCacheKey = sha1('last_mail_'.Utils::getClientIp()); + // Should be forbidden if sending email frequently - $this->withSession(['last_mail_time' => time()])->postJson('/auth/forgot', [ + $this->withCache([ + $lastMailCacheKey => time() + ])->postJson('/auth/forgot', [ 'captcha' => 'a' ])->assertJson([ - 'errno' => 1, + 'errno' => 2, 'msg' => trans('auth.forgot.frequent-mail') ]); + $this->flushCache(); + $this->flushSession(); // Should return a warning if user is not existed - $this->flushSession(); $user = factory(User::class)->create(); $this->withSession(['phrase' => 'a'])->postJson('/auth/forgot', [ 'email' => 'nope@nope.net', @@ -419,7 +424,9 @@ class AuthControllerTest extends TestCase ])->assertJson([ 'errno' => 0, 'msg' => trans('auth.forgot.success') - ])->assertSessionHas('last_mail_time'); + ]); + $this->assertCacheHas($lastMailCacheKey); + $this->flushCache(); Mail::assertSent(ForgotPassword::class, function ($mail) use ($user) { return $mail->hasTo($user->email); });