0
0

ThrottlesUtil.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace app\common\util;
  3. /**
  4. * 登录限流
  5. *
  6. * 使用说明,使用前先判断$account是否为空
  7. * 1.验证:(new ThrottlesUtil())->tooManyAttempts($account,$pre); true=锁定 false=未锁定
  8. * 2.登录成功,需要重置登录次数:(new ThrottlesUtil())->resetAttempts($account,$pre);
  9. * 3.不同体系的账号,可通过设置$pre前缀区分
  10. */
  11. class ThrottlesUtil
  12. {
  13. private $limitEnabled = true; // 是否开启限流 false=不开启 true=开启
  14. private $limitTime = 1*60; // 间隔时长(s)
  15. private $maxAttempts = 5; // 最大登录次数
  16. private $lockTime = 30*60; // 锁定时间(s)
  17. private $pre = "<|login|>"; // 前缀避免账号重复
  18. public function __construct($config = [])
  19. {
  20. if(isset($config['time'])){
  21. $this->limitTime = (int)$config['time'];
  22. }
  23. if(isset($config['attempts'])){
  24. $this->maxAttempts = (int)$config['attempts'];
  25. }
  26. if(isset($config['lock'])){
  27. $this->lockTime = (int)$config['lock'];
  28. }
  29. if(isset($config['enabled'])){
  30. $this->limitEnabled = $config['enabled'];
  31. }
  32. }
  33. /**
  34. * 检查是否锁定
  35. * @param $account 账号
  36. * @param string $pre // 缓存前缀,根据前缀区分不同类别账号
  37. * @return boolean false=未锁定 true=已锁定
  38. */
  39. public function tooManyAttempts($account,$pre = 'throttles'){
  40. if(!$this->limitEnabled){
  41. return false;
  42. }
  43. $key = $pre.$this->pre.$account;
  44. //检查是否存在对应lockout缓存
  45. if (cache($key.':lockout')) {
  46. return true;
  47. }
  48. //如果没有的话,attempts($key)返回$key对应的缓存中存储的登录次数
  49. if ($this->attempts($account,$pre) > $this->maxAttempts) {
  50. //如果已经超出限制,调用add方法添加对应lockout到缓存
  51. cache($key.':lockout',time() + $this->lockTime, $this->lockTime);
  52. //重置当前登录次数
  53. $this->resetAttempts($key);
  54. return true;
  55. }
  56. return false;
  57. }
  58. /**
  59. * 获取登录次数
  60. * @param $account 账号
  61. * @param string $pre 缓存前缀
  62. * @return int
  63. */
  64. public function attempts($account,$pre = 'throttles'){
  65. $key = $pre.$this->pre.$account;
  66. $times = cache($key); // ["1234567899","1234567892"]存储时间戳
  67. $ndata = [];
  68. $count = 0;
  69. $curTime = time();
  70. if($times){
  71. $data = json_decode($times,true);
  72. if(!empty($data)){
  73. $count = count($data);
  74. foreach ($data as $k=>$v){
  75. if($curTime - $v < $this->limitTime){ // 间隔小于时长有效
  76. $ndata[] = $v;
  77. }
  78. }
  79. }
  80. }
  81. $ndata[] = $curTime;
  82. cache($key,json_encode($ndata),$this->limitTime);
  83. return $count + 1;
  84. }
  85. /**
  86. * 重置登录次数
  87. * @param $account 账号
  88. * @param string $pre 缓存前缀
  89. */
  90. public function resetAttempts($account,$pre = 'throttles'){
  91. $key = $pre.$this->pre.$account;
  92. cache($key,NULL);
  93. cache($key.':lockout',NULL);
  94. }
  95. }