From 615ce6ae981b998a2a6ca26e7286e7cd611a0518 Mon Sep 17 00:00:00 2001 From: AntonioLiang <547052212@qq.com> Date: Mon, 14 Sep 2020 12:59:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8frontend=E6=B7=BB=E5=8A=A0=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E9=A2=91=E7=8E=87=E9=99=90=E5=88=B6=20=E9=99=90?= =?UTF-8?q?=E5=88=B6=E8=AE=BF=E9=97=AE=E9=A2=91=E7=8E=87,=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=99=BB=E5=BD=95=E7=9A=84=E6=96=B9=E6=B3=95=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E7=94=A8=E6=88=B7ID=E9=99=90=E5=88=B6=EF=BC=8C?= =?UTF-8?q?=E5=90=A6=E5=88=99=E9=80=9A=E8=BF=87IP=E9=99=90=E5=88=B6=20?= =?UTF-8?q?=EF=BC=88=E5=8F=AF=E9=98=B2=E6=AD=A2=E7=94=A8=E6=88=B7=E6=81=B6?= =?UTF-8?q?=E6=84=8F=E8=B0=83=E7=94=A8=E4=BB=98=E8=B4=B9API)=20=E5=9C=A8?= =?UTF-8?q?=E6=AF=8F=E4=B8=AA=E6=8E=A7=E5=88=B6=E5=99=A8=E7=9A=84=E5=89=8D?= =?UTF-8?q?=E9=9D=A2=E5=AE=9A=E4=B9=89=E6=AF=8F=E4=B8=AA=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E9=99=90=E5=88=B6=E9=A2=91=E7=8E=87=EF=BC=8C=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E4=B8=8D=E5=BC=80=E5=90=AF=EF=BC=8C=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E9=80=9A=E9=85=8D=E6=A8=A1=E5=BC=8F=20=E4=BE=8B=EF=BC=9Aprotec?= =?UTF-8?q?ted=20$VisitFrequency=20=3D=20['profile'=20=3D>=20'2/s,20/m'];?= =?UTF-8?q?=20=E8=A1=A8=E7=A4=BAprofile=E6=96=B9=E6=B3=95=20=E6=AF=8F?= =?UTF-8?q?=E7=A7=92=E6=9C=80=E5=A4=9A=E8=AE=BF=E9=97=AE2=E6=AC=A1?= =?UTF-8?q?=EF=BC=8C=E6=AF=8F=E5=88=86=E9=92=9F=E4=B8=8D=E8=B6=85=E8=BF=87?= =?UTF-8?q?20=E6=AC=A1=20=E5=8F=AF=E7=94=A8=E6=97=B6=E9=97=B4=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=EF=BC=8Cs=20=3D=20=E7=A7=92=EF=BC=8Cm=20=3D=20?= =?UTF-8?q?=E5=88=86=E9=92=9F,=20h=20=3D=20=E5=B0=8F=E6=97=B6,=20d=20=3D?= =?UTF-8?q?=20=E5=A4=A9=20=E6=9C=80=E5=A4=A7=E7=BC=93=E5=AD=9810=E5=A4=A9?= =?UTF-8?q?=EF=BC=8C=E8=B6=B3=E5=A4=9F=E4=BD=BF=E7=94=A8=E4=BA=86=20?= =?UTF-8?q?=E6=9C=89=E6=8F=90=E7=A4=BA=E4=BF=A1=E6=81=AF=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E8=87=AA=E8=A1=8C=E4=BF=AE=E6=94=B9=20=E5=9C=A8Frontend?= =?UTF-8?q?=E4=B8=AD=E5=AE=9A=E4=B9=89=E4=BA=86=E6=8A=A5=E9=94=99=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=9A=84URL=EF=BC=8C=E6=98=AFindex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/common/controller/Frontend.php | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/application/common/controller/Frontend.php b/application/common/controller/Frontend.php index f76fda0ff..ab2faaec8 100644 --- a/application/common/controller/Frontend.php +++ b/application/common/controller/Frontend.php @@ -3,6 +3,7 @@ namespace app\common\controller; use app\common\library\Auth; +use think\Cache; use think\Config; use think\Controller; use think\Hook; @@ -34,10 +35,19 @@ class Frontend extends Controller */ protected $noNeedRight = []; + /** + * 限制访问频率,需要登录的方法通过用户ID限制,否则通过IP限制 (可防止用户恶意调用付费API),缓存最大10天 + * @var array + * 例[ ['login' => '10/m,30/2h'] ,表示login 方法 每分钟最多访问10次,每两小时不超过30次 + * 可用时间单位,s = 秒,m = 分钟, h = 小时, d = 天 + */ + + protected $VisitFrequency = []; /** * 权限Auth * @var Auth */ + protected $auth = null; public function _initialize() @@ -75,12 +85,17 @@ class Frontend extends Controller $this->error(__('You have no permission')); } } + //访问频率限制,需要登录的情况 + $VisitFrequencyID = $this->auth->id; } else { // 如果有传递token才验证是否登录状态 if ($token) { $this->auth->init($token); } + //访问频率限制,不需要登录的情况 + $VisitFrequencyID = $this->request->ip(); } + $this->CheckVF($VisitFrequencyID,'/index'); $this->view->assign('user', $this->auth->getUser()); @@ -152,4 +167,77 @@ class Frontend extends Controller //刷新Token $this->request->token(); } + + /** + * 检查访问频率 + * @param string $VisitFrequencyID + * @param string $backurl + */ + protected function CheckVF($VisitFrequencyID,$backurl){ + $exptime = 864000; + $action = $this->request->action(); + $arr = array_map('strtolower', $this->VisitFrequency); + // 是否存在 + if (!array_key_exists (strtolower($action), $arr)) { + return false; + } + + $actionVF = $arr[$action]; + if(!$actionVF){ + return false; + } + $arr = is_array($actionVF) ? $actionVF : explode(',', $actionVF); + if (!$arr) { + return false; + } + $key = "VF".$VisitFrequencyID.$this->request->controller()."/".$action; + $vlog = Cache::get($key); + $minoldtime = 0; + $thistime = time(); + if($vlog) { + foreach ($arr as $SubVF) { + //转换表达式 + $maxVF = explode('/', $SubVF)[0]; + $timespan = explode('/', $SubVF)[1]; + if (strlen($timespan) == 1) { + $tunit = $timespan; + $tunitv = 1; + } else { + $tunit = substr($timespan, -1); + $tunitv = substr($timespan, strlen($timespan) - 1); + } + $timelast = $tunitv * ['s' => 1,'m' => 60,'h' => 3600,'d' => 86400][$tunit]; + + $oldtime = $thistime - $timelast; + $newlog = []; + $count = 0; + if($minoldtime ==0){ + $minoldtime = $oldtime; + } + if($oldtime < $minoldtime){ + $minoldtime = $oldtime; + } + //统计在过去的时间内访问了多少次 + foreach ($vlog as $t){ + if($t >= $oldtime && $t <= $thistime){ + $count ++; + } + } + $timedes = ['s' => '秒','m' => '分钟','h' => '小时','d' => '天'][$tunit]; + if($count >= $maxVF){ + $this->error(__('您的访问频率超过了%s次每%s%s',$maxVF,$tunitv,__($timedes)),$backurl); + } + } + //删除旧的访问记录 + foreach ($vlog as $t){ + if($t >= $minoldtime){ + $newlog[] = $t; + } + } + + } + //添加新的访问记录 + $newlog[] = $thistime; + Cache::set($key,$newlog,$exptime); + } } -- Gitee