Commit 5bb95737d5b40c5c074470966def8a5d589670fa

Authored by Nathanael Jourdane
1 parent b2c5ec48

Add a query limit for getParameters webservice

Showing 1 changed file with 49 additions and 1 deletions   Show diff stats
php/classes/WebServer.php
... ... @@ -83,6 +83,9 @@ class WebServer
83 83 private $wsUserMgr;
84 84 private $resultMgr, $myParamsInfoMgr;
85 85 private $dataFileName;
  86 + private $QUERY_TIME_INTERVAL;
  87 + private $MAX_QUERIES;
  88 + private $CLIENTS_ACCESS_PATH;
86 89  
87 90 function __construct() {
88 91 $this->userID = 'impex';
... ... @@ -90,6 +93,9 @@ class WebServer
90 93 $this->sessionID = $this->userID;
91 94 $this->myParamsInfoMgr = new ParamsInfoMgr();
92 95 $this->resultMgr = new WebResultMgr();
  96 + $this->QUERY_TIME_INTERVAL = 30; // Time interval to limit access, in seconds.
  97 + $this->MAX_QUERIES = 3; // Number of queries allowed in one time interval, per IP.
  98 + $this->CLIENTS_ACCESS_PATH = './clients'; // Path of the file containing clients access counters.
93 99 }
94 100  
95 101 protected function init($data) {
... ... @@ -117,6 +123,44 @@ class WebServer
117 123 return array('success' => true, 'vars' => $vars);
118 124 }
119 125  
  126 + // Returns true if the user reached its query limit.
  127 + private function isRateLimitReached() {
  128 + $currentTime = (int)(((new DateTime())->getTimestamp())/$this->QUERY_TIME_INTERVAL);
  129 + $ip = $_SERVER['REMOTE_ADDR'];
  130 + error_log("Client IP: $ip ; Current time: $currentTime\n");
  131 +
  132 + if(file_exists($this->CLIENTS_ACCESS_PATH)) {
  133 + $clients = file_get_contents($this->CLIENTS_ACCESS_PATH);
  134 + $matches = array();
  135 + if(preg_match("/($ip) (\d*) (\d*)/", $clients, $matches, PREG_OFFSET_CAPTURE)) {
  136 + error_log("Found an entry for this IP (". $matches[0][0] . ")\n");
  137 + $lastTime = (int)($matches[2][0]);
  138 + if($currentTime == $lastTime) {
  139 + $count = (int)($matches[3][0]);
  140 + if($count >= $this->MAX_QUERIES) {
  141 + error_log("Same time range and max count value reached: please wait a moment and try again.\n");
  142 + return true;
  143 + } else {
  144 + $count++;
  145 + error_log("Same time range, but max count value not reached yet: incrementing counter (" . ($this->MAX_QUERIES-$count) . "/$this->MAX_QUERIES).\n");
  146 + $clients = substr_replace($clients, $count, $matches[3][1], strlen($matches[3][0]));
  147 + }
  148 + } else {
  149 + error_log("New time range: resetting time entry.");
  150 + $clients = substr_replace($clients, "$ip $currentTime 1", $matches[0][1], strlen($matches[0][0]));
  151 + }
  152 + } else {
  153 + error_log("IP $ip not found: creating new time entry\n");
  154 + $clients = "$clients$ip $currentTime 1\n";
  155 + }
  156 + } else {
  157 + error_log("File not created yet: creating file and new time entry\n");
  158 + $clients = "$ip $currentTime 1\n";
  159 + }
  160 + file_put_contents($this->CLIENTS_ACCESS_PATH, $clients);
  161 + return false;
  162 + }
  163 +
120 164 private function setID(){
121 165  
122 166 $nb_min = 10000;
... ... @@ -549,7 +593,11 @@ class WebServer
549 593 ///////////////////////////////////////START GET DATASET ///////////////////////////////
550 594 public function getParameter($data) {
551 595  
552   - $multiParam = false;
  596 + if($this->isRateLimitReached()) {
  597 + return array('success' => false, 'message' => 'Rate limit reached. Please try again later.');
  598 + }
  599 +
  600 + $multiParam = false;
553 601  
554 602 $res = $this->init($data);
555 603  
... ...