123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- <?php
- namespace app\common\util;
- /**
- * 登录限流
- *
- * 使用说明,使用前先判断$account是否为空
- * 1.验证:(new ThrottlesUtil())->tooManyAttempts($account,$pre); true=锁定 false=未锁定
- * 2.登录成功,需要重置登录次数:(new ThrottlesUtil())->resetAttempts($account,$pre);
- * 3.不同体系的账号,可通过设置$pre前缀区分
- */
- class ThrottlesUtil
- {
- private $limitEnabled = true; // 是否开启限流 false=不开启 true=开启
- private $limitTime = 1*60; // 间隔时长(s)
- private $maxAttempts = 5; // 最大登录次数
- private $lockTime = 30*60; // 锁定时间(s)
- private $pre = "<|login|>"; // 前缀避免账号重复
- public function __construct($config = [])
- {
- if(isset($config['time'])){
- $this->limitTime = (int)$config['time'];
- }
- if(isset($config['attempts'])){
- $this->maxAttempts = (int)$config['attempts'];
- }
- if(isset($config['lock'])){
- $this->lockTime = (int)$config['lock'];
- }
- if(isset($config['enabled'])){
- $this->limitEnabled = $config['enabled'];
- }
- }
- /**
- * 检查是否锁定
- * @param $account 账号
- * @param string $pre // 缓存前缀,根据前缀区分不同类别账号
- * @return boolean false=未锁定 true=已锁定
- */
- public function tooManyAttempts($account,$pre = 'throttles'){
- if(!$this->limitEnabled){
- return false;
- }
- $key = $pre.$this->pre.$account;
- //检查是否存在对应lockout缓存
- if (cache($key.':lockout')) {
- return true;
- }
- //如果没有的话,attempts($key)返回$key对应的缓存中存储的登录次数
- if ($this->attempts($account,$pre) > $this->maxAttempts) {
- //如果已经超出限制,调用add方法添加对应lockout到缓存
- cache($key.':lockout',time() + $this->lockTime, $this->lockTime);
- //重置当前登录次数
- $this->resetAttempts($key);
- return true;
- }
- return false;
- }
- /**
- * 获取登录次数
- * @param $account 账号
- * @param string $pre 缓存前缀
- * @return int
- */
- public function attempts($account,$pre = 'throttles'){
- $key = $pre.$this->pre.$account;
- $times = cache($key); // ["1234567899","1234567892"]存储时间戳
- $ndata = [];
- $count = 0;
- $curTime = time();
- if($times){
- $data = json_decode($times,true);
- if(!empty($data)){
- $count = count($data);
- foreach ($data as $k=>$v){
- if($curTime - $v < $this->limitTime){ // 间隔小于时长有效
- $ndata[] = $v;
- }
- }
- }
- }
- $ndata[] = $curTime;
- cache($key,json_encode($ndata),$this->limitTime);
- return $count + 1;
- }
- /**
- * 重置登录次数
- * @param $account 账号
- * @param string $pre 缓存前缀
- */
- public function resetAttempts($account,$pre = 'throttles'){
- $key = $pre.$this->pre.$account;
- cache($key,NULL);
- cache($key.':lockout',NULL);
- }
- }
|