Php 如何限制一分钟内发出的用户请求数
用户将通过类似于Php 如何限制一分钟内发出的用户请求数,php,url,ip,limit,Php,Url,Ip,Limit,用户将通过类似于script.php?userid=222的URL按编号请求文件。此示例将显示文件#222的记录 现在我想将每个(远程IP)用户的文件数限制为一分钟内最多5条不同的记录。但是,用户应该能够多次访问相同的id记录 因此,用户可以多次访问文件222,但如果(远程IP)用户在一分钟内访问了5个以上的其他不同记录,则应显示错误 例如,假设在一分钟内发出以下请求: script.php?userid=222 script.php?userid=523 script.php?userid=6
script.php?userid=222的URL按编号请求文件。此示例将显示文件#222的记录
现在我想将每个(远程IP)用户的文件数限制为一分钟内最多5条不同的记录。但是,用户应该能够多次访问相同的id记录
因此,用户可以多次访问文件222,但如果(远程IP)用户在一分钟内访问了5个以上的其他不同记录,则应显示错误
例如,假设在一分钟内发出以下请求:
script.php?userid=222
script.php?userid=523
script.php?userid=665
script.php?userid=852
script.php?userid=132
script.php?userid=002
然后在最后一次请求时,它应该显示错误消息
以下是基本代码:
$id = $_GET['userid'];
if (!isset($_GET['userid']) || empty($_GET['userid'])) {
echo "Please enter the userid";
die();
}
if (file_exists($userid.".txt") &&
(filemtime($userid.".txt") > (time() - 3600 * $ttime ))) {
$ffile = file_get_contents($userid.".txt");} else {
$dcurl = curl_init();
$ffile = fopen($userid.".txt", "w+");
curl_setopt($dcurl, CURLOPT_URL,"http://remoteserver.com/data/$userid");
curl_setopt($dcurl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($dcurl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($dcurl, CURLOPT_TIMEOUT, 50);
curl_setopt($dcurl, CURLOPT_FILE, $ffile);
$ffile = curl_exec($dcurl);
if(curl_errno($dcurl)) // check for execution errors
{
echo 'Script error: ' . curl_error($dcurl);
exit;
}
curl_close($dcurl);
$ffile = file_get_contents($userid.".txt");
}
您可以使用会话机制,而不是依赖于IP地址。您可以通过会话\u start()
创建会话作用域,然后存储与同一用户会话相关的信息
然后,我建议在此会话范围内保留用户在以前的请求中使用的唯一ID的列表,以及请求的时间,忽略任何重复的请求,这些请求总是被允许的。一旦此列表在最后一分钟内包含5个带有时间戳的元素并请求新ID,您将显示错误并拒绝查找
下面是执行此操作的代码。您应该在检查userid参数的存在性之后,在检索文件内容之前放置它:
// set the variables that define the limits:
$min_time = 60; // seconds
$max_requests = 5;
// Make sure we have a session scope
session_start();
// Create our requests array in session scope if it does not yet exist
if (!isset($_SESSION['requests'])) {
$_SESSION['requests'] = [];
}
// Create a shortcut variable for this array (just for shorter & faster code)
$requests = &$_SESSION['requests'];
$countRecent = 0;
$repeat = false;
foreach($requests as $request) {
// See if the current request was made before
if ($request["userid"] == $id) {
$repeat = true;
}
// Count (only) new requests made in last minute
if ($request["time"] >= time() - $min_time) {
$countRecent++;
}
}
// Only if this is a new request...
if (!$repeat) {
// Check if limit is crossed.
// NB: Refused requests are not added to the log.
if ($countRecent >= $max_requests) {
die("Too many new ID requests in a short time");
}
// Add current request to the log.
$countRecent++;
$requests[] = ["time" => time(), "userid" => $id];
}
// Debugging code, can be removed later:
echo count($requests) . " unique ID requests, of which $countRecent in last minute.<br>";
// if execution gets here, then proceed with file content lookup as you have it.
作者:
当然,这对用户不太友好,因为它会影响任何新会话,也会影响那些没有试图通过删除cookie进行欺骗的用户
登记处
更好的方法是只允许注册用户使用查找服务。为此,您必须提供用户数据库和身份验证系统(例如,基于密码的)。请求应记录在数据库中,并由用户ID键入。如果随后启动新会话,用户必须首先再次进行身份验证,一旦通过身份验证,将从数据库检索请求历史记录。这样,用户就无法通过更改客户端配置(IP地址、cookies、并行使用多个设备等)来规避此问题。最可靠的方法是将IP地址与访问的文件id和日期时间字段一起保存在某个位置(如文件或数据库)。但是如果你有很多用户,这会在mysql服务器上产生相当大的服务器流量和负载。具有超时的cookie或会话将占用更少的资源。但它们也很容易规避。(删除cookie或关闭浏览器以销毁会话)。我想你必须首先在可靠性和可伸缩性之间做出选择。我在这里说的是最可靠的,因为现在你不能真正依赖IP地址。像Tor这样的浏览器只需按下一个按钮,就可以在5秒内为您提供一个新的IP地址。所以我可能首先会问自己,这是否真的值得麻烦?非常感谢,它就像一个魅力,令人惊叹!你是大师,你解决了我的问题!提前祝您新年快乐和圣诞快乐。会议通过饼干进行标识。如果有人删除了cookie,或者没有存储cookie,那么他可以发送无限数量的请求。@BojanHrnkas,绝对可以!我添加了一段关于这个主题的内容和一条要求认证的建议。@trincot保护注册本身怎么样?对于用户体验,我希望用户在注册后直接登录,但如果用户存在或不存在,这会给出反馈。这可能是需要询问的问题。继续并发布一个问题。
if (!isset($_SESSION['requests'])) {
$_SESSION['requests'] = [];
}
$initial_delay = 10; // 10 seconds delay for new sessions
if (!isset($_SESSION['requests'])) {
$_SESSION['requests'] = array_fill(0, $max_requests,
["userid" => 0, "time" => time()-$min_time+$initial_delay]
);
}