| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 | <?phpnamespace 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);    }}
 |