Method 1
通过key记录IP:
rate.limiting:$IP
,同时初始时设置期限为60秒,如果超时则重新设置,否则进行判断,当一分钟内访问超过100次,则禁止访问。
$isKeyExists = rate.limiting:$IP
if ($isKeyExists == 1) {
$times = INCR rate.limiting:$IP
if ($times > 100){
print '超过访问限制'
exit
}
}else{
MULTI
INCR rating.limiting:$IP
EXPIRE rating.limiting:$IP 60
EXEC
}
考虑到如果请求的频率在每秒10次,每分钟请求9次,那么即使它是有问题的访问,但是依然限制不了。So
Method 2
$listLength = LLEN rate.limiting:$IP
if ($listLength < 10) {
LPUSH rate.limiting:$IP now()
}else{
$time = LINDEX rate.limiting:$IP, -1
if (now() - $time < 60){
print "超过访问限制"
exit
}else{
LPUSH rate.limiting:$IP now()
LTRIM rate.limiting:$IP, 0, 9
}
}
计算该IPkey的list长度,即该IP访问的时间队列,如果小于10次,那么将每次访问的时间入栈。否则,当访问次数满了10次,计算当前时间与最近一次访问时间的时间差,如果小于60秒,那么禁止访问,否则重置队列,重新存储访问时间。
PHP实现redis限制单ip、单用户的访问次数功能
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth("php001");
//这个key记录该ip的访问次数 也可改成用户id
//$key = 'userid_11100';
$key=get_real_ip();
//限制次数为5
$limit = 5;
$check = $redis->exists($key);
if($check){
$redis->incr($key);
$count = $redis->get($key);
if($count > 5){
exit('请求太频繁,请稍后再试!');
}
}else{
$redis->incr($key);
//限制时间为60秒
$redis->expire($key,60);
}
$count = $redis->get($key);
echo '第 '.$count.' 次请求';
//获取客户端真实ip地址
function get_real_ip(){
static $realip;
if(isset($_SERVER)){
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$realip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}else if(isset($_SERVER['HTTP_CLIENT_IP'])){
$realip=$_SERVER['HTTP_CLIENT_IP'];
}else{
$realip=$_SERVER['REMOTE_ADDR'];
}
}else{
if(getenv('HTTP_X_FORWARDED_FOR')){
$realip=getenv('HTTP_X_FORWARDED_FOR');
}else if(getenv('HTTP_CLIENT_IP')){
$realip=getenv('HTTP_CLIENT_IP');
}else{
$realip=getenv('REMOTE_ADDR');
}
}
return $realip;
}
?>
PHP实现限制IP访问的方法
//获取客户端ip
if (getenv("HTTP_CLIENT_IP"))
$ip = getenv("HTTP_CLIENT_IP");
else if(getenv("HTTP_X_FORWARDED_FOR"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if(getenv("REMOTE_ADDR"))
$ip = getenv("REMOTE_ADDR");
else $ip = "Unknow";
$ALLOWED_IP=array('10.144.39.132');
//允许访问的ip
$check_ip_arr= explode('.',$ip);
//ip参数拆分成数组
if(!in_array($ip,$ALLOWED_IP)) {
$bl=false;
foreach ($ALLOWED_IP as $val){
if(strpos($val,'*')!==false){
//发现有*号替代符
$arr=array();
$arr=explode('.', $val);
$bl=true;
//用于记录循环检测中是否有匹配成功的
for ($i=0;$i<4;$i++){
if($arr[$i]!='*'){
//不等于* 就要进来检测,如果为*符号替代符就不检查
if($arr[$i]!=$check_ip_arr[$i]){
$bl=false;
break;
//终止检查本个ip 继续检查下一个ip
}
}
}
//end for
if($bl){
//如果是true则终止匹配
break;
}
}
}
//end foreach
if(!$bl){
$return=array(
'status'=>2,
'msg'=>'该IP无权限访问',
'data'=>$ip
);
echo json_encode($return);
exit();
}
}