From 5bb95737d5b40c5c074470966def8a5d589670fa Mon Sep 17 00:00:00 2001 From: Nathanael Jourdane <nathanael.jourdane@irap.omp.eu> Date: Mon, 13 Nov 2017 19:53:21 +0100 Subject: [PATCH] Add a query limit for getParameters webservice --- php/classes/WebServer.php | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/php/classes/WebServer.php b/php/classes/WebServer.php index f20ea07..c1e0ab8 100644 --- a/php/classes/WebServer.php +++ b/php/classes/WebServer.php @@ -83,6 +83,9 @@ class WebServer private $wsUserMgr; private $resultMgr, $myParamsInfoMgr; private $dataFileName; + private $QUERY_TIME_INTERVAL; + private $MAX_QUERIES; + private $CLIENTS_ACCESS_PATH; function __construct() { $this->userID = 'impex'; @@ -90,6 +93,9 @@ class WebServer $this->sessionID = $this->userID; $this->myParamsInfoMgr = new ParamsInfoMgr(); $this->resultMgr = new WebResultMgr(); + $this->QUERY_TIME_INTERVAL = 30; // Time interval to limit access, in seconds. + $this->MAX_QUERIES = 3; // Number of queries allowed in one time interval, per IP. + $this->CLIENTS_ACCESS_PATH = './clients'; // Path of the file containing clients access counters. } protected function init($data) { @@ -117,6 +123,44 @@ class WebServer return array('success' => true, 'vars' => $vars); } + // Returns true if the user reached its query limit. + private function isRateLimitReached() { + $currentTime = (int)(((new DateTime())->getTimestamp())/$this->QUERY_TIME_INTERVAL); + $ip = $_SERVER['REMOTE_ADDR']; + error_log("Client IP: $ip ; Current time: $currentTime\n"); + + if(file_exists($this->CLIENTS_ACCESS_PATH)) { + $clients = file_get_contents($this->CLIENTS_ACCESS_PATH); + $matches = array(); + if(preg_match("/($ip) (\d*) (\d*)/", $clients, $matches, PREG_OFFSET_CAPTURE)) { + error_log("Found an entry for this IP (". $matches[0][0] . ")\n"); + $lastTime = (int)($matches[2][0]); + if($currentTime == $lastTime) { + $count = (int)($matches[3][0]); + if($count >= $this->MAX_QUERIES) { + error_log("Same time range and max count value reached: please wait a moment and try again.\n"); + return true; + } else { + $count++; + error_log("Same time range, but max count value not reached yet: incrementing counter (" . ($this->MAX_QUERIES-$count) . "/$this->MAX_QUERIES).\n"); + $clients = substr_replace($clients, $count, $matches[3][1], strlen($matches[3][0])); + } + } else { + error_log("New time range: resetting time entry."); + $clients = substr_replace($clients, "$ip $currentTime 1", $matches[0][1], strlen($matches[0][0])); + } + } else { + error_log("IP $ip not found: creating new time entry\n"); + $clients = "$clients$ip $currentTime 1\n"; + } + } else { + error_log("File not created yet: creating file and new time entry\n"); + $clients = "$ip $currentTime 1\n"; + } + file_put_contents($this->CLIENTS_ACCESS_PATH, $clients); + return false; + } + private function setID(){ $nb_min = 10000; @@ -549,7 +593,11 @@ class WebServer ///////////////////////////////////////START GET DATASET /////////////////////////////// public function getParameter($data) { - $multiParam = false; + if($this->isRateLimitReached()) { + return array('success' => false, 'message' => 'Rate limit reached. Please try again later.'); + } + + $multiParam = false; $res = $this->init($data); -- libgit2 0.21.2