用户将通过URL等号码请求文件script.php?userid=222
.此示例将显示文件#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"); }
trincot.. 11
您可以使用会话机制,而不是依赖IP地址.您可以通过创建会话范围session_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.
"; // if execution gets here, then proceed with file content lookup as you have it.
会话由客户端上的cookie维护.用户可以删除这样的cookie,从而获得新会话,这将允许用户在不考虑先前请求的情况下发出新请求.
解决这个问题的一种方法是为每个新会话引入一个冷却期.例如,您可以让他们等待10秒钟才能发出第一个请求.为此,请在上面的代码中替换:
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而试图欺骗的用户.
更好的方法是仅允许注册用户查找服务.为此,您必须提供用户数据库和身份验证系统(例如基于密码).请求应记录在数据库中,并由用户的ID键入.如果然后新会话开始,则用户必须首先再次进行身份验证,并且一旦经过身份验证,就会从数据库中检索请求历史记录.这样,用户就不能通过改变客户端配置(IP地址,cookie,并行使用多个设备,......)来欺骗它.
您可以使用会话机制,而不是依赖IP地址.您可以通过创建会话范围session_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.
"; // if execution gets here, then proceed with file content lookup as you have it.
会话由客户端上的cookie维护.用户可以删除这样的cookie,从而获得新会话,这将允许用户在不考虑先前请求的情况下发出新请求.
解决这个问题的一种方法是为每个新会话引入一个冷却期.例如,您可以让他们等待10秒钟才能发出第一个请求.为此,请在上面的代码中替换:
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而试图欺骗的用户.
更好的方法是仅允许注册用户查找服务.为此,您必须提供用户数据库和身份验证系统(例如基于密码).请求应记录在数据库中,并由用户的ID键入.如果然后新会话开始,则用户必须首先再次进行身份验证,并且一旦经过身份验证,就会从数据库中检索请求历史记录.这样,用户就不能通过改变客户端配置(IP地址,cookie,并行使用多个设备,......)来欺骗它.