BotBan

Защита формы от спам-ботов без капчи: рабочие способы

Три способа, которые не задают посетителю ни одного вопроса, и объясняем, какой из них чего стоит.

3 мин чтения

Спам в формах делают в основном простые скрипты, которые обходят сайты подряд и заполняют всё, что похоже на форму. Против них не нужна тяжёлая артиллерия — нужны признаки, которых у человека не бывает.

Ловушка

Самый надёжный из простых способов. В форму добавляется поле, невидимое человеку:

<input type="text" name="website" tabindex="-1" autocomplete="off"
       aria-hidden="true"
       style="position:absolute;left:-9999px;width:1px;height:1px;opacity:0">

На сервере:

if (!empty($_POST['website'])) {
    // Человек этого поля не видит. Значит, форму заполнила программа.
    exit;
}

Три важные детали.

Не используйте type="hidden". Многие боты специально пропускают скрытые поля, зная про ловушки. Обычное текстовое поле, спрятанное стилями, ловит лучше.

Не называйте поле honeypot или trap. Название вроде website, fax или company2 выглядит настоящим.

Добавьте aria-hidden и tabindex="-1". Иначе поле увидит скринридер, и человек со слабым зрением его заполнит — вы заблокируете именно того, кого меньше всего хотели.

Замер времени

Записываете момент открытия формы и проверяете на сервере:

$elapsed = time() - (int) $_POST['form_opened_at'];

if ($elapsed < 2) {
    // Заполнить форму осмысленно за две секунды нельзя.
}

Метку надо подписывать, иначе её подделают:

$token = hash_hmac('sha256', (string) time(), $secret);

Осторожно: блокировать по одному этому признаку не стоит. Автозаполнение браузера срабатывает мгновенно, и живой человек с сохранёнными данными отправит форму за секунду. Считайте это доводом, а не приговором.

Признаки автоматики

Всё, что видно из самого запроса, без вопросов посетителю:

  • User-Agent, в котором написано python-requests, curl, Go-http-client;
  • отсутствие Accept-Language у клиента, представившегося браузером;
  • отсутствие Referer при отправке формы со страницы вашего же сайта;
  • отправка POST без единого предшествующего GET на эту страницу.

Последний признак хорош тем, что его сложно обойти дёшево: боту приходится сначала загрузить страницу, а это удваивает стоимость атаки.

Чего не делать

Не прячьте кнопку отправки за JavaScript целиком. Часть людей останется без формы: отключённый JS, старый браузер, режим экономии трафика.

Не блокируйте по одному признаку. У каждого есть живые исключения. Складывайте.

Не показывайте боту, что он пойман. Ответ «спасибо, заявка принята» для заполненной ловушки — лучше, чем «отказано»: автор скрипта не узнает, что его отсекли, и не станет чинить.

Что остаётся

Ловушка и тайминг снимают подавляющую часть массового спама. Если спамят целенаправленно и через настоящий браузер, добавляются поведенческие признаки — двигал ли посетитель мышью, есть ли у браузера отпечаток графики, управляется ли он программой. Собрать это руками можно, но проще взять готовое.

Читайте также