laravel通过ThrottlesLogins这个trait来实现登录验证的功能,我们只需要在控制器中use ThrottlesLogins这个trait便可以开启这个功能,注意:默认的make:auth的login控制器在trait AuthenticatesUsers中开启了该功能。
下面我们来分析登录限流是怎样实现的。
登录限流实际上是通过判断连续登录失败的次数是否超过我们限制的次数来实现的
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
hasTooManyLoginAttempts()判断当前的登录次数是否超过限制,如果超过限制,则触发一个锁定事件并通知其监听者,然后返回一个锁定的响应。
其中具体的逻辑如下,先来看看是如果判断登录次数是否超过限制的。
protected function hasTooManyLoginAttempts(Request $request)
{
//限制次数5,锁定时间1分钟
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request), 5, 1
);
}
$this->limiter()用于获取一个Illuminate\Cache\RateLimiter实例,所以看出我们实际上是调用了底层的RateLimiter中的tooManyAttempts()方法。
public function tooManyAttempts($key, $maxAttempts, $decayMinutes = 1)
{
//has()方法检查是否存在对应lockout缓存
if ($this->cache->has($key.':lockout')) {
return true;
}
//如果没有的话,attempts($key)返回$key对应的缓存中存储的登录次数
if ($this->attempts($key) > $maxAttempts) {
//如果已经超出限制,调用add方法添加对应lockout到缓存
$this->cache->add($key.':lockout', Carbon::now()->getTimestamp() + ($decayMinutes * 60), $decayMinutes);
//重置当前登录次数
$this->resetAttempts($key);
return true;
}
return false;
}
$this->cache返回的是一个实现了Illuminate\Contracts\Cache\Repository接口的对象,相关的依赖由container注入,这里我们就不继续深入了,相关分析注释在代码中。
$this->cache->add($key.':lockout', Carbon::now()->getTimestamp() + ($decayMinutes * 60), $decayMinutes);
这里通过设置一个有效期为$decayMinutes的locktout缓存,传入的参数Carbon::now()->getTimestamp() + ($decayMinutes * 60)
设置了缓存的失效时间,也就是锁定的时间
如果经过判断,我们的登录次数已经超过的界定,那么,我们就会调用$this->fireLockoutEvent($request);
来通知该时间的监听者,具体的监听者我们可以在EventServiceProvider中的listeners数组中添加下面这项:
'Illuminate\Auth\Events\Lockout' =>['your listener', ]
通知后我们就需