FrequencyLimitation.php
1.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
namespace app\api\behavior;
use think\Cache;
class FrequencyLimitation
{
public function run(&$params)
{
// 行为逻辑
$reqUri = trim(request()->path(), '/');
$res = preg_match('/^(api\/cloudapi\/)/', $reqUri);
if ($res){
$statistics = preg_match('/^(api\/cloudapi\/statistics\/)/', $reqUri);
if (!$statistics){//数据中心大屏统计页面接口不做限制
if (!$this->requestAccess()){
echo json(['code'=>99999,'msg'=>'接口调用过于频繁','time'=>time(),'data'=>null])->send();die;
}
}
}
}
/**
* 访问频率限制
* @param int $time 一样的参数每秒请求次数
* @param int $limit 每分钟限制访问次数
* @return bool
*/
protected function requestAccess($time=1,$limit=20){
//获取访问用户的IP
$ip=md5(request()->ip());
//获取访问的接口路径
$path=request()->path();
//将IP和访问的接口路径md5加密成一个字符串,这样子就代表同一个客户访问的接口。
$UV=md5($ip.$path);
//每个IP和接口每分钟不能超过的次数
$cacheIp=Cache::get($UV)?:0;
if($cacheIp){
if($cacheIp>$limit){
return false;
}else{
Cache::inc($UV,1);
}
}else{
Cache::set($UV,1,60);
}
//将每个请求的IP地址、参数和路径拼接成同一个用户的一个完全相同的接口。
$post=json_encode(request()->post());
$name=md5($path.$post);
//每个相同的数据多少时间内不能请求
$cache=Cache::get($name);
if($cache==$ip){
return false;
}else{
Cache::set($name,$ip,$time);
return true;
}
}
}