Я хочу, чтобы мой сценарий не был затоплен – если пользователь нажимает F5, он выполняет скрипт каждый раз.
Я хочу предотвратить это и разрешить одно выполнение скрипта за 2 секунды, есть ли какое-то решение для этого?
Вы можете использовать memcache для этого.
Простой демонстрационный скрипт
$memcache = new Memcache (); $memcache->connect ( 'localhost', 11211 ); $runtime = $memcache->get ( 'floodControl' ); if ((time () - $runtime) < 2) { die ( "Die! Die! Die!" ); } else { echo "Welcome"; $memcache->set ( "floodControl", time () ); }
Это всего лишь пример кода. Есть и другие вещи, которые следует учитывать, например
A. Лучшее обнаружение IP
адресов (Proxy, Tor)
B. Текущие действия
C. Максимальное исполнение за минуту и т. Д. …
D. Запрет пользователя после максимального наводнения и т. Д.
EDIT 1 – Улучшенная версия
Применение
$flood = new FloodDetection(); $flood->check(); echo "Welcome" ;
Класс
class FloodDetection { const HOST = "localhost"; const PORT = 11211; private $memcache; private $ipAddress; private $timeLimitUser = array ( "DEFAULT" => 2, "CHAT" => 3, "LOGIN" => 4 ); private $timeLimitProcess = array ( "DEFAULT" => 0.1, "CHAT" => 1.5, "LOGIN" => 0.1 ); function __construct() { $this->memcache = new Memcache (); $this->memcache->connect ( self::HOST, self::PORT ); } function addUserlimit($key, $time) { $this->timeLimitUser [$key] = $time; } function addProcesslimit($key, $time) { $this->timeLimitProcess [$key] = $time; } public function quickIP() { return (empty ( $_SERVER ['HTTP_CLIENT_IP'] ) ? (empty ( $_SERVER ['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER ['REMOTE_ADDR'] : $_SERVER ['HTTP_X_FORWARDED_FOR']) : $_SERVER ['HTTP_CLIENT_IP']); } public function check($action = "DEFAULT") { $ip = $this->quickIP (); $ipKey = "flood" . $action . sha1 ( $ip ); $runtime = $this->memcache->get ( 'floodControl' ); $iptime = $this->memcache->get ( $ipKey ); $limitUser = isset ( $this->timeLimitUser [$action] ) ? $this->timeLimitUser [$action] : $this->timeLimitUser ['DEFAULT']; $limitProcess = isset ( $this->timeLimitProcess [$action] ) ? $this->timeLimitProcess [$action] : $this->timeLimitProcess ['DEFAULT']; if ((microtime ( true ) - $iptime) < $limitUser) { print ("Die! Die! Die! $ip") ; exit (); } // Limit All request if ((microtime ( true ) - $runtime) < $limitProcess) { print ("All of you Die! Die! Die! $ip") ; exit (); } $this->memcache->set ( "floodControl", microtime ( true ) ); $this->memcache->set ( $ipKey, microtime ( true ) ); } }
вы можете использовать файлы cookie (которые могут быть отключены), поэтому не очень хорошая идея, или вы можете использовать для хранения своего ip-адреса в базе данных, поэтому, если больше X пытается с одного и того же IP-адреса, тогда не выполняйте код, просто if else, вам понадобится таблица с ip-адресами, время запроса, количество попыток
ЕСЛИ вы не хотите использовать базы данных, вы можете использовать следующий код
$file = "file.txt"; $file_content = file_get_contents($file); $fh = fopen($file, 'w') or die("could not open file"); $now = time(); if($now - $file_content > 60){ // your code here fwrite($fh, $now); }else{ echo "Try again later"; } fclose($fh);
но в этом случае это не будет для каждого посетителя, а скорее для всех из них (так скажем, что пользователь A пришел и выполнил сценарий, пользователь B не сможет выполнить его до 60 секунд.
Лучшим способом было бы сохранить время на сервере. Если вы оставите информацию на стороне клиента, вам будет легко пройти мимо.
Я бы, например, сохранил метку времени в таблице. Это вводит и проверяет спам вашего скрипта. И было бы легко установить терпимость.
используйте кеш-память apc или mencache для хранения информации, хранящейся в базе данных, или чтения из файла. Я считаю, что это время / ресурс