前言
因为我自己上线了一个免费的API接口站,想利用Redis来限制恶意调用、爬虫等情况,所以写了这么一个类。
代码
<?php
/**
* @function:Re拦截器
* @author:木小果
* @link:https://blog.muxiaoguo.cn
* @date:2022/2/27
*/
class ReInterceptor {
public $redis;
public $cycle;
public $limit;
public $outtime;
/**
* 初始化Redis
* @param string $pass 密码
* @param string $ip IP
* @param int $port 端口
*/
public function __construct($pass,$ip='127.0.0.1',$port=6379) {
$this->redis = new Redis();
$this->redis->connect($ip, $port);
$this->redis->auth($pass);
if ($this->redis->ping() != '+PONG') die("Redis abnormal");
}
/**
* 设置Redis限制参数
* @param int $cycle 一个周期时长,单位:毫秒
* @param int $limit 一个周期内访问数量上限,单位:次
* @param int $outtime 限制用户访问的时间,单位:秒
* @return null
*/
public function setReCof($cycle,$limit,$outtime) {
$this->cycle = $cycle;
$this->limit = $limit;
$this->outtime = $outtime;
}
/**
* 检查KEY
* @param string $key 用户唯一ID
* @return int $result 周期内调用次数
*/
public function check($key) {
if ($this->redis->exists($key)) {
$this->redis->incr($key);
$count = $this->redis->get($key);
if ($count > $this->limit) {
$this->redis->expire($key, $this->outtime);
$rem = $this->redis->pttl($key);
$msg = '请求频繁,请在 [time] 秒后再试';
$msg = str_replace('[time]',($rem / 1000), $msg);
die($this->proMessage(3301,$msg));
}
return $count;
} else {
$this->redis->incr($key,0);
$this->redis->pexpire($key, $this->cycle);
}
return $this->redis->get($key);
}
/**
* 返回JSON提示语(提示消息)
* @param int $code 错误代码
* @param string $msg 错误内容
* @return string $result 返回数据
*/
public function proMessage($code, $msg, $data=[]) {
$result = [//返回数据统一处理
'code' => $code,
'msg' => $msg,
'data' => $data
];
return json_encode($result,320);
}
}
?>
用法
/*实例化*/
$redis = new ReInterceptor('redisPassword');
/*设置基本参数,解释:1000毫秒内调用次数超过5次封禁用户30秒*/
$redis->setReCof(1000, 5, 30);
/*检查KEY*/
$count = $redis->check(getRealIp());
echo '周期内调用次数:' . $count;