Php 基于ip限制页面访问次数

Php 基于ip限制页面访问次数,php,Php,我想知道如何防止单个ip地址占用过多带宽并快速访问我的网页。也就是说,检查用户的ip地址(我认为$\u SERVER['REMOTE\u ADDR']?),检查此用户的最新访问,计算时差,并在间隔较短时阻止呈现页面。我说得对吗?如果是这样,我如何在不消耗太多资源和/或时间的情况下完成这项工作?如果有一种数据库方法,它不会导致太多锁吗?Apache mod\u带宽允许控制某些IP i、 e.带宽 最佳方法取决于您试图阻止的对象。如果是真正的用户不断刷新页面,那么(a)你真的想阻止他们吗?他们是你的

我想知道如何防止单个ip地址占用过多带宽并快速访问我的网页。也就是说,检查用户的ip地址(我认为
$\u SERVER['REMOTE\u ADDR']
?),检查此用户的最新访问,计算时差,并在间隔较短时阻止呈现页面。我说得对吗?如果是这样,我如何在不消耗太多资源和/或时间的情况下完成这项工作?如果有一种数据库方法,它不会导致太多锁吗?

Apache mod\u带宽允许控制某些IP

i、 e.
带宽


最佳方法取决于您试图阻止的对象。如果是真正的用户不断刷新页面,那么(a)你真的想阻止他们吗?他们是你的用户!?,(b)您可以使用基于会话的方法来避免数据库命中。如果是机器人,那么你就不能依赖会话(因为它们可能没有发送会话头,或者它们目前可能是恶意的机器人,会绕过会话)

如果是真正的用户,那么假设您可以设置会话cookie,您将需要以下内容:

<?php
$min_seconds_between_refreshes = 3;

session_start();

if(array_key_exists('last_access', $_SESSION) && time()-$min_seconds_between_refreshes <= $_SESSION['last_access']) {
  // The user has been here at least $min_seconds_between_refreshes seconds ago - block them
  exit('You are refreshing too quickly, please wait a few seconds and try again.');
}
// Record now as their last access time
$_SESSION['last_access'] = time();
?>

如果是机器人,那么您可能会使用类似的逻辑实现基于数据库的解决方案


事实上,在这两种情况下,正确的解决方案可能是在应用服务器前面缓存代理服务器。这将减少主应用服务器上的负载,意味着您不必太担心这种情况。

以下是使用的洪水检测代码。如果用户在一分钟内访问次数超过50次,他将被阻塞300秒。远程地址用于标识客户端

<?php 

$limit = 50; 
$seconds = 60;  
$block_for_seconds = 300;

$status = 'OK';

$memcache = new Memcache;
$memcache->connect('localhost', 11211);

$ip = $_SERVER['REMOTE_ADDR'];

$r = $memcache->get($ip, array('c', 't'));

$c = 1; // count
$init_time = time();
if($r) {
  $s = $r[3]; // status
  $c = $r[0]+1;
  $init_time = $r[1];
  if($s == 'TOO_MANY_REQUESTS') {
    $d = time()-$r[1]; // time since block
    if($block_for_seconds-$d > 0) {  // still blocked
      die('Flood detected!! You are going to wait '.($block_for_seconds-$d).' and try again.');
    } else {  // block is over
      $status = 'OK';
      $init_time = time();
      $c = 0;
    }
  }

  $new_time = time();
  if($c > $limit) {  // check if happened within a minute
    $time_elapsed = $new_time - $init_time;
    if($time_elapsed < $seconds) {  
      $status = 'TOO_MANY_REQUESTS'; 
    }
    print "time elapsed: $time_elapsed, count:$c";
    $c = 0;
    $init_time = time();
  }
}
print_r($r);
$memcache->set($ip, array($c, $init_time, $new_time, $status) );
?>


如果一个用户真的想以这种方式攻击您的站点,那么一个简单的PHP IP块并不能阻止他们。特别是因为请求已经进入PHP,并且无论如何都使用了资源。您缺少的最重要的东西是,服务器是您的吗,例如VPS,专用的还是您可以访问防火墙和/或您可以获得软件包?或者只是托管共享主机服务器是专用的。你的权利,如果请求命中php,那么攻击者已经赢了。我喜欢在访问php之前限制客户端,但我不想只限制他们使用的带宽。假设有一个客户端实现得像一个简单的多线程爬虫程序,它正在下载我网站中的所有页面。我能阻止谁呢?我想阻止邪恶的用户/机器人,他们可能想用一个简单的爬虫来使用我服务器的所有带宽。数据库方法的开销如何?对,所以会话方法不起作用。DB会有一些开销,但您可能会在每个请求中多次命中DB?一个额外的不会有多大区别。然而,这将是一张难看的桌子,你必须写一些东西来定期清理老访客。@eugene的解决方案对我来说似乎是最好的。