Иногда боты достают конкретно, можно банить их по ip.
Для этого имеем в виду то, что ip в таблице со счётчиком num==0 нормален, а всё что выше – нет, и мы его откидываем.
Итак, строим такую таблицу:
CREATE TABLE `ips_blocked` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dtm` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ip` varchar(44) NOT NULL COMMENT 'ip адрес', `ua` tinytext NOT NULL COMMENT 'User agent', `num` int(11) NOT NULL DEFAULT '0' COMMENT 'кол-во попаданий', `rem` tinytext NOT NULL COMMENT 'примечание', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
ip туда добавляем вручную, т.к. этот процесс редкий, если нет – пишите скрипт для добавления туда ip.
По умолчанию num равен 0.
Итак, перед записью заявки проверяем ip по этой таблице, и если он есть и его номер num больше 0, откидываем заявку:
$ip = empty($_SERVER['REMOTE_ADDR']) ? '' : htmlspecialchars($_SERVER['REMOTE_ADDR']); if(DB::columnIntPrepared('SELECT 1 FROM ips_blocked WHERE ip=? AND num>0', array($ip))) { DB::execute("UPDATE ips_blocked SET num=num+1 WHERE ip=?", array($ip)); report('Ваш ip находится в чёрном списке. Пришлите вашу заявку нам на email.'); }
Таким образом мы можем пропустить первое случайное попадание в чёрный список по ip, а если оно повторится – всё, заявки с данного ip больше не принимаем совсем.
Таким образом, если мы опять обнаружили спамерский ip, ставим его номер 1 в таблице ips_blocked.
На этом всё, до свидания!
P.S. Для ip версии 4 (IPv4) наиболее эффективно наверное использовать тип INT(11),
и при этом каждый раз при добавлении/выборке его в/из таблицы надо использовать соотв. функции, например так:
Добавление: INSERT INTO ips_blocked VALUES (…, INET_ATON(?), …)
Выборка: SELECT INET_NTOA(ip) AS ip
Здесь вместо знака вопроса при добавлении вставляем ip в подготовленное SQL-выражение.
Но я не стал этого делать, а сделал тип поля VARCHAR и длину поля вообще 44, чтобы при случае иметь возможность добавлять IPv6, не знаю уже, когда этот момент настанет. ))))