Laravel 登录失败次数限制 等待时间递增
Laravel 本身已实现了登录失败次数限制的功能。在使用 Laravel 的登录验证时,登录失败次数限制预设是:
- 失败5次,
1分钟后
才可再次登录
但如果要求的功能是:
- 失败3次,
1分钟后
才可登录 - 再失败3次,
3分钟后
才可登录 - 再失败3次,
5分钟后
才可登录
要如何实现?下面将实际示范此登录失败次数限制的功能。
版本
Laravel 5.8 以上
改写登录类别设定
app\Http\Controllers\Auth\LoginController.php
<?php
...
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use App\Cache\AdvancedRateLimiter;
class LoginController extends Controller
{
use AuthenticatesUsers;
...
/**
* The maximum number of attempts to allow.
*
* @var int
*/
protected $maxAttempts = 3;
/**
* The number of minutes to throttle for.
*
* @var int|float|int[]|float[]
*/
protected $decayMinutes = [1, 3, 5];
/**
* Get the rate limiter instance.
*
* @return \App\Cache\AdvancedRateLimiter
*/
protected function limiter()
{
return app(AdvancedRateLimiter::class);
}
/**
* Increment the login attempts for the user.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function incrementLoginAttempts(Request $request)
{
$this->limiter()->hit(
$this->throttleKey($request), array_map(function ($decayMinute) {
return (int) ($decayMinute * 60);
}, (array) $this->decayMinutes())
);
}
}
在 LoginController
类中,增加自订方法复盖掉 AuthenticatesUsers
类原本的方法:
limiter
方法是返回登录失败次数限制的类,原本是返回RateLimiter
类(实现登录失败次数限制的类),但本例要扩充新方法,因此返回了我们下面创建的子类别AdvancedRateLimiter
。$maxAttempts
属性是设定登录失败次数。$decayMinutes
属性是登录失败达上限后,须等待的分钟数。但我们要实现的功能是每次都等待不一样的时间,因此传入一个数组,输入每次的等待分钟数。
如果只是要修改 Laravel 原本的次数设定,新增 $maxAttempts
属性及 $decayMinutes
属性并设定值即可完成。
擴充登录失败次数限制功能
新增类别 AdvancedRateLimiter
:
app\Cache\AdvancedRateLimiter.php
<?php
namespace App\Cache;
use Illuminate\Cache\RateLimiter;
class AdvancedRateLimiter extends RateLimiter
{
/**
* Increment the counter for a given key for a given decay time.
*
* @param string $key
* @param int|int[] $decaySeconds
* @return int
*/
public function hit($key, $decaySeconds = 60)
{
if (is_array($decaySeconds)) {
if (! $this->cache->has($key.':timer')) {
if (! $this->cache->has($key.':step')) {
$this->cache->add($key.':step', 0, 86400);
} else {
$this->cache->increment($key.':step');
}
}
$step = $this->cache->get($key.':step', 0);
$step = $step < count($decaySeconds) ? $step : count($decaySeconds) - 1;
$decaySeconds = $decaySeconds[$step];
}
return parent::hit($key, $decaySeconds);
}
/**
* Clear the hits and lockout timer for the given key.
*
* @param string $key
* @return void
*/
public function clear($key)
{
$this->cache->forget($key.':step');
parent::clear($key);
}
}
hit
方法是在登錄錯誤後,執行登錄錯誤次數記錄遞增的方法。為了實現每次登錄錯誤等待的時間可以不一樣,我們讓傳入的變數$decayMinutes
可以接受傳入数组,第一次登錄錯誤等待時間為数组[0]
的分鐘數(本例為1分鐘),第二次為数组[1]
的分鐘數(例:3分鐘),而第三次為数组[2]
的分鐘數(例:5分鐘),之後的登錄錯誤等待時間皆為数组的最後的元素的分鐘數。clear
是成功登入後,將時間、次數重設,下一次再登入錯誤後,將從頭開始計數。
此時登录失败次数限制的功能已改寫完成,再次登入並輸入錯誤的帳號或密碼,重複數次即可看到結果。
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
尝试运行了下,就报错了~
@shadow123 您是不是使用 Laravel 5.4? 此功能 Laravel 5.5 以上才支援。
@Chenshin 看到了 是我版本问题 ;麻烦了
这里应该乘以 60 吧
提示怎样即时反馈
@kinchuam 请问要提示什么即时反馈?