我想知道如何防止单个IP地址使用过多带宽并快速访问我的网页。也就是说,检查用户的IP地址(我认为$_SERVER['REMOTE_ADDR']
?),检查该用户的最新访问,计算时差并在间隔较短时阻止呈现页面。我对吗?如果是这样,如何在不消耗太多资源和/或服务器时间的情况下执行此操作?如果有数据库方法,是不是会导致锁定太多?
答案 0 :(得分:5)
最好的方法取决于你想阻止的对象。如果它是不断更新页面的真正用户,那么(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();
?>
如果它是机器人,那么你可能会实现一个基于数据库的解决方案,具有类似的逻辑。
事实上,在这两种情况下,正确的解决方案可能是应用程序服务器前面的缓存代理服务器。这将减少主应用服务器的负载,并且意味着您不必担心这样的情况。
答案 1 :(得分:4)
Apache mod_bandwidth允许控制某些IP
即。 BandWidth <domain|ip|all> <rate>
答案 2 :(得分:2)
以下是使用Memcache的洪水检测代码。如果用户在一分钟内超过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) );
?>