Как быстро избавиться от спама без CAPTCHA

Если у вас на сайте есть хоть одна форма обратной связи, то наверняка вы ощутили проблему безумного количества спама, который приходит на почту сотрудникам. Какое-то время это можно стойко терпеть и притворяться, что люди не тратят своё рабочее время на расчистку почты, не теряют настоящие заявки и заказы в пучинах папки "спам". 
 


Однако, рано или поздно, в отдел разработки поступает просьба: установить CAPTCHA. И тут уже довольно вяло могут протестовать те, кто знает о недостатках такого решения: 

Captcha — это нечитабельный код на картинке, необходимость ввода которого раздражаетпосетителей и, как следствие, в разы снижает конверсию любой формы. Можно перечислить ещё с десяток минусов, но этого пункта достаточно, чтобы отказаться от использования такого метода защиты в пользу любого другого. 


632

 

К счастью, сделать замену можно за 10 минут. Ниже приведем простой трюк:

Создаём скрытую переменную, которая хранится в сессии пользователя.
 

Внимание! Непонятные буквы:

  1. $_SESSION[‘userhash’];
Эта переменная содержит в себе уникальный ключ, который состоит из MD5 хеша, IP-адреса клиента и случайной строки.
 

Внимание! Опять непонятные буквы:

  1. $_SESSION[‘userhash’] = md5($_SERVER[‘REMOTE_ADDR’].$randomString);
Не знаю, почему мне захотелось сделать именно такого вида строку, но это просто первое, что пришло в голову. Вы можете сделать всё то же самое, используя другие данные. Теперь эту строку нам нужно передать в Java Script, чтобы потом, при отправке формы, передавать это значение на сервер.

Всё действительно так просто, как кажется :) Однако любой Script Kiddie (подросток, который пишет вредоносных ботов, за небольшое вознаграждение, используя готовые скрипты и программы — прим. ред.),  который увидит хэш, натравит бота и на него. Чтобы немного усложнить им задачу, можно сделать следующее: каждый символ в хэше преобразуется в ASCII-код этого символа, а в Java Script собирается в единую строку. Такой метод работает ТОЛЬКО на клиентских машинах.

Внимание! Вам ещё не надоели непонятные буквы?

PHP:

  1. $hashArray = Array();
  2. for ($i = 0; $i < strlen($_SESSION['userhash']); $i++)
  3. $hashArray[] = ord($_SESSION['userhash'][$i]);
  4. $hash = implode(',', $hashArray);
  5. $_SESSION['userhash_coded'] = $hash;

Java Script:

  1. var a = String.fromCharCode();

В конечном виде это выглядит примерно так:

  1. var a = String.fromCharCode(53, 48, 49, 48, 101, 54, 52, 98, 101, 102, 56, 50, 99, 99, 50, 50, 51, 53, 100, 57, 49, 56, 100, 56, 56, 101, 97, 98, 48, 51, 56, 54);

Минусы такого решения, конечно, есть:

Если у пользователя отключен JS, то метод не сработает. Но я, если честно, ни разу в жизни не встречал людей, которые отключают JS. Кроме того, сейчас эта проблема не так актуальна, как пару лет назад. Большинство пользователей интернтет сидит в соц. сетях, где наличие включённого JS — необходимость.

Итак, после того как мы собрали в строку ASCII-коды, нам необходимо вставить это значение в скрытое поле формы, при инициализации страницы. Также мы можем сделать это при отправке формы. В общем передать переменную можно, как угодно. Ну а проверка на стороне сервера очень проста.

Внимание! Это последний раз:

  1. if (!isset($_POST['hiddenHash']) || $_POST['hiddenHash'] !== $_SESSION['userhash'])
  2. die();
Как правило, боты не выполняют JS код, так что если не передан параметр hiddenHash, то мы понимаем, что это бот и обходимся с ним безжалостно, вызывая функцию die();
 
После внедрения этой простой защиты, спам вас больше не побеспокоит, а посетителям не будет сниться по ночам злостная CAPTCHA.