如何限制一分钟内发出的用户请求数 [英] How to limit the number of user requests made within a minute

查看:160
本文介绍了如何限制一分钟内发出的用户请求数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用户将通过诸如 script.php?userid = 222 之类的URL按号码请求文件。此示例将显示文件#222的记录。

A user will request a file by number via a URL like script.php?userid=222. This example would show the record of file #222.

现在我想将每个(远程IP)用户的文件数限制为最多5个不同的记录分钟。但是,用户应该能够在任何时间访问相同的id记录。

Now I want to limit the number of files per (remote IP) user to a maximum of 5 different records in a minute. However, the user should be able to access the same id record any number of time.

因此用户可以多次访问文件#222,但如果(远程IP)用户在一分钟内访问超过5个其他不同的记录,然后它应该显示错误。

So the user could access file #222 any number of times, but if the (remote IP) user accesses more than 5 other different records in a minute, then it should show an error.

例如,假设在一分钟内发出以下请求:

For example, suppose within a minute the following requests are made:

script.php?userid=222
script.php?userid=523
script.php?userid=665
script.php?userid=852
script.php?userid=132
script.php?userid=002

然后在最后一个请求时它应该显示错误消息。

then at the last request it should show the error message.

这是基本代码:

$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地址,您可以使用会话机制。您可以通过 session_start()创建会话范围,然后存储使用相同用户会话的信息。

Instead of relying on the IP address, you could use the session mechanism. You can create a session scope via session_start(), and then store information that sticks with the same user session.

然后,我建议在此会话范围内保留用户先前请求中使用的唯一ID列表以及请求的时间,忽略始终允许的任何重复请求。一旦此列表包含5个元素,并且在最后一分钟内有一个时间戳,并且请求新ID,则显示错误并拒绝查找。

I would then suggest to keep in this session scope the list of unique IDs used in previous requests that user made, together with the time of the request, ignoring any repeated requests, which are always allowed. As soon as this list contains 5 elements with a time stamp within the last minute and a new ID is requested, you show the error and refuse the lookup.

这是执行此操作的代码。您应该在检查 userid 参数的存在之后以及在检索文件内容之前将其放置:

Here is the code that does this. You should place it right after you have checked the presence of the userid argument, and before the retrieval of the file contents:

// 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 ...



会话由客户端上的cookie维护。用户可以删除此类cookie,以便获得新会话,这将允许用户在不考虑先前请求的情况下发出新请求。

Deleted session cookies...

Sessions are maintained by cookies on the client. The user may delete such cookies, an so get a new session, which would allow the user to make new requests without regard of what was previously requested.

获取的一种方式这是为每个新会议引入一个冷静期。例如,您可以让他们等待10秒钟,然后才能发出第一个请求。要做到这一点,请在上面的代码中替换:

One way to get around this is to introduce a cool-down period for each new session. For instance, you could have them wait for 10 seconds before a first request can be made. To do that, replace in above code:

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] 
    );
}

这当然不太方便用户,因为它影响任何新会话,也是不想通过删除cookie来欺骗的用户。

This is of course less user friendly as it affects any new session, also of users who are not trying to cheat by deleting cookies.

更好的方法是只允许向注册用户查询服务。为此,您必须提供用户数据库和身份验证系统(例如基于密码)。请求应记录在数据库中,并由用户的ID键入。如果然后新会话开始,则用户必须首先再次进行身份验证,并且一旦经过身份验证,就会从数据库中检索请求历史记录。通过这种方式,用户不会通过更改客户端配置(IP地址,cookie,并行使用多个设备,......)来欺骗它。

The better way is to only allow the lookup services to registered users. For this you must provide a user database and authentication system (for example password based). The requests should be logged in the database, keyed by the user's ID. If then a new session starts, the user must first authenticate again, and once authenticated the request history is retrieved from the database. This way the user cannot cheat around it by changing something on their client configuration (IP address, cookies, employing multiple devices in parallel, ...)

这篇关于如何限制一分钟内发出的用户请求数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆