How to limit the number of user requests made within a minute How to limit the number of user requests made within a minute php php

How to limit the number of user requests made within a minute


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.

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.

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 scopesession_start();// Create our requests array in session scope if it does not yet existif (!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.

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.

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'] = [];}

By:

$initial_delay = 10; // 10 seconds delay for new sessionsif (!isset($_SESSION['requests'])) {    $_SESSION['requests'] = array_fill(0, $max_requests,        ["userid" => 0, "time" => time()-$min_time+$initial_delay]     );}

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.

Registration

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, ...)


<?php // session_start();// session_destroy();// exit;echo index();function index(){    $id = rand(000,020);    $min_time = 60;    $max_requests = 5;    // $id = 0;    session_start();    $repeat = false;        if(!isset($_SESSION["countRecent"]) && !isset($_SESSION["countRecent"]) && !isset($_SESSION["countRecent"])){        $_SESSION["countRecent"] = 1;        $_SESSION["time"] = time();        $_SESSION['userid'][] = $id;    }else{        if ($_SESSION["countRecent"] >= $max_requests) {            if(!in_array($id,$_SESSION['userid'])){                if ($_SESSION["time"] <= time() - $min_time) {                    $_SESSION["countRecent"] = 1;                    $_SESSION["time"] = time();                }else{                    return("Too many requests in a short time wait ". ( $_SESSION["time"] - (time() - $min_time)  )). " Seconds";                }            }        }else{            if(!in_array($id,$_SESSION['userid'])){                $_SESSION["countRecent"] = $_SESSION["countRecent"] + 1;                $_SESSION['userid'][] = $id;            }        }    }    return "Your Result goes here.. id: $id  Counts: ". $_SESSION["countRecent"];}

Try this. Fast , low memory usage

But not secure;

also use database

<?php $conn = mysqli_connect("localhost", "root", "","db_name") or die("Could not connect database");$id = rand(0,99);// $id = 100;echo index($id);function index($id,$user=1,$ip='192.168.0.10',$max_requests = 5,$min_time = 20){    global $conn;    $time = time();    $req = "INSERT INTO `limit_api_by_ip2`(`id`, `ip`, `time`, `user`, `req`)     VALUES (null,INET_ATON('$ip'),'$time','$user',1)    ON DUPLICATE KEY UPDATE req=req+1;";        $req2 = "INSERT INTO `limit_api_by_ip2`(`id`, `ip`, `time`, `user`, `req`)     VALUES (null,INET_ATON('$ip'),'$time','$user',1)    ON DUPLICATE KEY UPDATE req=1,`time`='".time()."' ;";        $reqid = "INSERT INTO `limit_api_by_ip2_count`(`id`, `user`, `ids`) VALUES (null,'$user',$id)";        $getid = "SELECT `ids` FROM `limit_api_by_ip2_count` WHERE user = $user and ids = $id limit 1;";        $gettime = "SELECT `time`,`req` FROM `limit_api_by_ip2` WHERE user = $user and ip = INET_ATON('$ip') limit 1;";    // $id = 0;    $q = mysqli_query($conn,$getid);    $c = mysqli_num_rows($q);    if($c==0){        $get_time = mysqli_query($conn,$gettime);        $c1 = mysqli_num_rows($get_time);        if($c1==0){            mysqli_query($conn,$req);            mysqli_query($conn,$reqid);        }else{            $row = mysqli_fetch_row($get_time);                        if ($row[1] >= $max_requests) {                if ($row[0] <= (time() - $min_time)) {                    mysqli_query($conn,$req2);                    mysqli_query($conn,$reqid);                }else{                    return "Too many requests in a short time wait ".($row[0]-(time() - $min_time))." Seconds";                }            }else{                mysqli_query($conn,$req);                mysqli_query($conn,$reqid);            }        }    }else{            }    if(isset($row[1]))    {        $cc = "Counts: ".$row[1];        $dd = "new id: $id";    }else{        $cc = '';        $dd = "old id: $id";    }    return "Your Result goes here.. $dd  ".$cc; }