Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何限制一分钟内发出的用户请求数_Php_Url_Ip_Limit - Fatal编程技术网

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