Загрузка...

Борьба со спамом на сайте

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

По сути, мы можем защищаться от спама на двух уровнях: серверном (PHP) и клиентском (JavaScript). Ярким примером защиты от спама на PHP может послужить пресловутая капча.

Алгоритм таков: мы с помощью PHP рисуем картинку с буквами и цифрами (да, PHP умеет рисовать не хуже Paint), запоминаем эти символы, например, по средствам cookie, выводим их пользователю на экран и просим его ввести слово с картинки, после чего он их вводит и жмёт кнопку "отправить". Нам приходят эти цифры, мы сверяем пришедшие цифры со значением в cookies пользователя и если они равны, то выполняем нужное пользователю действие, например, публикуем комментарий.

Как сделать капчу на PHP своими руками я расскажу в другой статье, а сейчас я хочу выделить некоторые недостатки этого метода:

  • Различать символы на картинке одно из самых нелюбимых действий для пользователей. Лично я миллион раз забрасывал регистрацию и передумывал оставлять комментарий из-за такой ерунды, а мог бы повысить конверсию сайта. Да, раз я бросил регистрацию из-за наличия капчи, значит, я не сильно-то был и заинтересован, это правда. Но кто знает, возможно, мне бы понравился этот форум или сайт и я бы даже стал его постоянным посетителем. Да что мне вам объяснять, в Интернете есть куча статей, анализов и диаграмм, которые показывают, насколько капча снижает конверсию для сайтов.
  • Нагрузка на сервер. Несмотря на то, что спам-бот не оставит комментарий и не пошлёт вам тикет по форме обратной связи - он всё равно создаст какую-то нагрузку на ваш сервер. Когда он заполнит все поля и неверно заполнит капчу он "нажмёт" на кнопку "отправить", в результате чего все данные уйдут на обработку вашему серверу, чтобы тот определил: прошёл посетитель проверку или нет.

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

Минус у подобных способов один: обойти яваскрипт ещё легче, чем обойти проверки на PHP. Но под словом «обойти» я подразумеваю хакера, который целенаправленно будет писать скрипт конкретно под ваш сайт.

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

Также хочется отметить, что способ, описанный в этой статье дальше, естественно, уже зарекомендовал себя. Я вам "лишь бы что-то" никогда не советую :)

Анти-спам для Joomla 2.5 + VirtueMart 2

Этот простой алгоритм и не менее простой скрипт я придумал для одного из своих интернет-магазинов на Joomla 2.5 + VirtueMart 2. Мне постоянно приходил спам из формы "Задайте вопрос об этом товаре", после чего я залез в отвечающий за неё файл (/components/com_virtuemart/views/askquestion/tmpl/form.php) и установил там свой анти-спам: проблема была решена!

Результат работы

До тех пор пока пользователь не введёт ответ, мы не отрисуем ему кнопку "отправить":

Защита от спама

Пользователь вводит правильный ответ и мы на лету создаём для него кнопку:

Работа скрипта

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

Создаём скрипт анти-спама своими руками

Перейдём к созданию. Для того чтобы создать свой собственный анти-спам на Яваскрипте + немного PHP (для динамики) нам потребуется форма обратной связи (подопытный кролик), знание о многомерных массивах в PHP и функция, которую мы использовали для ротации баннеров на сайте – shuffle().

То есть из всего вышеперечисленного, новым для моих постоянных читателей окажется только сам код JS. Но давайте обо всём по порядку: первым делом нам нужно создать многомерный массив на PHP, в который мы будем заносить вопросы и ответы для нашего анти-спама, после чего мы будем перемешивать массив и выводить случайный вопрос:

<?php
$spam[] = array("Три плюс семь равно...","v.match(/^десять$/i)||v=='10'");
$spam[] = array("Пять минус пять равно...","v.match(/^ноль$|^нуль$/i)||v=='0'");
$spam[] = array("Шесть плюс один равно...","v.match(/^семь$/i)||v=='7'");

shuffle($spam); /* Перемешиваем массив */
?>

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

$spam[] = array("Три плюс семь равно...","v.match(/^десять$/i)||v=='10'");

Итак в круглых скобочках мы указываем 2 ячейки: первая (до запятой) это наш вопрос, а вторая – ответ. В нашем примере в ответ мы записали следующее:

v.match(/^десять$/i)||v=='10'

Мы перечислили два возможных варианта ответа, первый варианта (до ||):

v.match(/^десять$/i)

В нём мы указали регулярное выражение, а именно: ответ должен содержать слово "десять" и ничего кроме этого, а флаг i после слеша обозначает, что регистр не имеет значения. Тоже самое можно было записать и так:

v=='десять'

Но тогда бы регистр имел значение, и слово "Десять", написанное с большой буквы оказалось бы не верным.

Количество ответов может быть каким угодно, вот пример, когда правильных ответов четыре:

$spam[] = array("4 - 2 = ?","v=='два'||v=='две'||v=='двум'||v=='двумя'");

Если вам нужно указать несколько слов внутри регулярного выражения, то это, как я уже не раз писал в других статьях (например, в статье про дубли страниц), делается с помощью одинарной вертикальной черты:

$spam[] = array("5 - 5 = ?","v.match(/^ноль$|^нуль$/i)||v=='0'");

Пример выше можно переделать и так:

$spam[] = array("5 - 5 = ?","v.match(/^ноль$|^нуль$|^0$/i)");

В данном случае мы число 0 тоже занесли в регулярное выражение. Надеюсь смысл как записывать ответ, вам понятен, здесь нет абсолютно ничего сложного, особенно, если вы читали мои предыдущие статьи о регулярных выражениях.

Теперь вернёмся к форме обратной связи, чтобы не лить лишней воды, сразу напишу, как она у нас должны выглядеть теперь:

<div onclick="openn(this)" id="callback"></div><div id="body-form">
<form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
  Имя: <input required="required" maxlength="30" type="text" name="name" /><br />
  Телефон: <input required="required" maxlength="30" type="text" name="phone" /><br />
  Сообщение: <br /><textarea rows="7" cols="50" required="required" name="message">Пожалуйста, перезвоните на указанный номер.</textarea>
  <input type="hidden" name="check" value="fd13vv" />
  <strong><?php echo $spam[0][0] ?></strong>
  Ответ: <input type="text" id="myspam" size="20"/>
</form>
</div>

В чём суть? Мы полностью удалили кнопку "отправить":

<input type="submit" value="Отправить!" />

Теперь она будет отрисовываться на лету с помощью Яваскрипта только после того, как пользователь правильно ответит на наш вопрос. Вместо кнопки "отправить" у нас появилось две новых строчки:

<strong><?php echo $spam[0][0] ?></strong>
Ответ: <input type="text" id="myspam" size="20"/>

В первой мы отрисовываем случайный вопрос и заключаем его в тег strong, чтобы он выделялся полужирным. Во второй строчке мы указываем поле для ввода ответа на вопрос. Внимание! Не меняйте id у этого input, а если меняете, то не забудьте поменять его и в JS, вот, кстати, и он:

<script type='text/javascript'>
document.getElementById('myspam').onkeyup = function(e){var v = this.value;if(<?php echo $spam[0][1] ?>){var inp = document.createElement('DIV');inp.innerHTML = '<input type="submit" value="Отправить!" />';this.parentNode.insertBefore(inp,this.nextSibling);this.onkeyup = null;}}
</script>

Я специально записал его в одну строчку, чтобы ваши страницы загружались быстрее. В этом javaScript коде мы указываем id поля, в который пользователь должен ввести свой ответ, у нас это myspam. Далее перечисляем все правильные варианты ответов, которые должны прийти в переменную v и если они приходят, то отрисовываем кнопку "отправить".

Примечание:

JS в коде должен находиться ниже формы, например, сразу после неё. Лично я размещаю его в самом конце страницы, перед закрывающимся тегом body. При этом JS нельзя выносить во внешний файл, так как в нём присутствует PHP код.

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

{

}