9 Июль 2016

Простой метод защиты веб-форм от спам-ботов без использования каптчи

Simple method to protect web-form from spam bot without captcha

Традиционным способом получения обратной связи в сети Интернет является использование веб-форм. Однако, их широкое распространение, удобство и лёгкость встраивания на сайт, привели к тому, что веб-формы стали использоваться многочисленными спам-ботами для рассылки нежелательных рекламных сообщений.

В этой связи встал вопрос о защите этого способа контактов от методов автоматизированной рассылки. Одним из наиболее популярных методов в настоящее время является использование каптчи, которая представляет собой вариант теста Тьюринга для определения, вводит ли информацию на сайте человек или машина.

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

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

1. Методика распознования ввода человеком

Главный вопрос в поставленной проблеме это способ отличить ввод информации в форму человеком от машинной отправки. Человек, в отличие от ботов, всегда вводит информацию в форму с клавиатуры. Исключение может составлять, пожалуй, лишь система автопозаполнения типовых полей, которую предлагают все современные браузеры.

Если рассмотреть типовую веб-форму, то в ней можно увидеть четыре основных поля для ввода контактной информации: имя, контактый e-mail, телефон, и, собственно, сам текст, который и является сутью обращения.

<form method="post" class="message" id="form" action="mail.php">
    <input type="hidden" name="action" value="send"/>
    <input type="text" name="name" placeholder="Ваше имя" value="" tabindex="1"/>
    <input type="text" name="addr" placeholder="e-mail" value="" tabindex="2"/>
    <input type="text" name="phone" placeholder="Телефон" value="" tabindex="3"/>
    <textarea name="text" placeholder="Сообщение" tabindex="4"></textarea>
    <input type="submit" value="Отправить" tabindex="5"/>
</form>

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

Простейшим способом для отслеживания является подсчёт числа нажатий на клавиши и сравнение данного подсчёта с реальной длинной текста переданного через отслеживаемое поле формы. Причём делать эту проверку следует на серверной части кода сайта, который обрабатывает данную веб-форму. В приведённом примере это скрипт mail.php.

2. Код проверки

Javascript, который является стандартным средством на стороне браузера клиента, даёт широкий набор инструментов по обработке событий клавиатуры на данной веб странице. Воспользуемся методом onkeyup для отслеживания нажатий, повесив на него функцию подсчёта их количества. Поле приобретёт вид.

...
    <textarea name="text" placeholder="Сообщение" onkeyup="javascript:countme();" tabindex="4"></textarea>
...

Далее напишем простой скрипт для обработки, не забыв при этом, что нам будет необходимо передавать и сам результат подсчёта. Для этого лучше всего будет воспользоваться скрытым полем input. В целях ввести в заблуждение анализаторы HTML-кода, которые используют спам-боты, это поле не будет сразу добавлено на страницу в ходе вёрстки, а будет сгенерированно при помощи того же Javascript при её загрузке. Для этого разместим следующий код ближе к концу страницы, поместив туда и саму функцию подсчёта нажатий клавиш.

<script type="text/javascript">
var ct = 0;
var addCount = document.createElement('input');
    addCount.type = "hidden";
    addCount.id = "count";
    addCount.name = "count";
    addCount.value = "0";
    document.getElementById('form').appendChild(addCount);
function countme() {
    document.getElementById('count').value = ++ct;
}
</script>

Здесь в секции инициализации обнуляется счётчик с именем ct, далее создаётся скрытое поле с именем count и описывается функция подсчёта countme(), которая будет увеличивать счётчик на единицу и подставлять его значение в поле value только что созданного скрытого поля.

Теперь при отправке формы нам будет достаточно получить значение полей текстового ввода и счётчика и сравнить в их серверной части на PHP для получения заключения о том, кто её заполнял - человек с клавиатуры или робот. Значение нажатий клавиш всегда будет больше или равно количеству символов в тексте, получаемое через функцию strlen().

<?php
...
$msg=$_POST['text'];
$count=$_POST['count'];
...
if (strlen($msg) <= $count) {
    // сделать что-то с этим
}
...
?>

Хорошим тоном будет также предварительно проверить наличие в передаваемой формой набора данных значения из созданного скрытого поля count, к примеру PHP функцией isset($_POST['count']), что позволить отсеять боты попавшиеся в ловушку с его динамическим добавлением.

Дополнение. В ходе опытной эксплуатации было выявлено ограничение данного метода, связанное с функцией автоподстановки слов в устройствах с тач-экраном. В этом случае проверенные системы эмулируют меньшее количество событий "нажатие на клавишу", чем будет содержать набранный текст. Поэтому лучшим вариантом будет использование PHP функции str_word_count() вместо strlen() не забыв, при этом, изменить равенство в нужную сторону. Таким образом с количеством нажатий клавиш будет сравниваться не количество символов в отправленном тексте, а количество слов, которое будет однозначно меньше счётчика. Надёжность защиты от ботов же при этом ничуть не пострадает.

3. PROFIT!

Статья была полезной? Тогда прошу не стесняться и поддерживать деньгами через PayPal или Яндекс.Деньги.


antispam  dev  html  javascript  php