Как сделать скрипт анти-спама своими руками на JavaScript + PHP

"Все аспекты самостоятельного создания и продвижения сайтов
от практика с многолетним опытом." — блог Рудь Сергея
info@site-on.net
Заметка: активирована адаптивная версия сайта, которая автоматически подстраивается под небольшой размер Вашего браузера и скрывает некоторые детали сайта для удобства чтения. Приятного просмотра!
16.06.2013

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

Как обычно, созданный в этой статье скрипт полностью универсален и будет работать для любого сайта с любой CMS.

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

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

По сути, мы можем защищаться от спама на двух уровнях: серверном (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% спама идёт через автоматические скрипты и мало кому станет интересно писать скрипт ради одного вашего сайта.

Обновление от 26.10.2013: практика показала, что если ваш сайт не на Joomla, а на голом PHP, то нужно обязательно добавить в PHP обработчик проверку на ответ (заполнено ли поле с ответом), например, с помощью функции !empty($_POST["имя поля с ответом"])

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

С уважением, .
Пожалуйста, оцените эту статью
Средняя оценка: 4.75 из 5 (проголосовало: 4)
Статья оказалась вам полезной? Подпишитесь, чтобы не пропустить новые!

Ваш email:
Вы можете помочь развитию проекта, сделав всего 1 клик:
Спасибо!
Пожалуйста, прокомментируйте, как Вам моя статья?
Имя:
Комментарий:

Если Вы хотите вставить код, пожалуйста, заключайте его в [code][/code]

Подписаться на новые комментарии:

E-mail:


Защита от спама: пожалуйста, напишите слово "сел" справа налево
Ответ:
Подписаться на новые комментарии без комментирования - Email:
Защита от спама: пожалуйста, напишите слово "сел" справа налево
Ответ:

26.10.2013 09:40:44 Антон:
Здравствуйте, подскажите новичку

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

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


это тоже в index.php вставлять?
26.10.2013 10:41:01 Сергей отвечает:
Да, в самом вверху можете. Кстати сейчас обновлю статью, допишу кое-что полезное.
20.03.2014 15:17:36 Александр отвечает:
<div id="modal" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h2>Lorem Ipsum</h2>
</div>
<?php
if(!empty($thanks)){
echo $thanks;
}
?>
<div class="modal-body">
<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>
</div>
</div>
</tr>
</tbody>
</table>
</div>

Подскажите, без модального окна всё работает нормально, вставляю вашу форму в модальное окно и ничего не происходит, при нажатии на отправить.
20.03.2014 17:23:36 Сергей отвечает:
Быстро подсказать не могу. Возможно скрипт JS не даёт это сделать. Смотрите консоль в браузере и исправляйте ошибки.

Ответить на комментарий

Использую для работы
Мои расширения
Свежие статьи
Рекомендую
Горячо обсуждаемые
Подписка
  • Следовать в twitter:
  • Подписаться по RSS:
  • Подписаться по E-mail:
  • Следить ВКонтакте:
  • Следить на Facebook:
Пользовательское соглашение об условиях использования сайта и Политика конфиденциальности
Перепечатывание или копирование материалов сайта (текста, изображений и другого содержимого) для их публичного или коммерческого использования в сети Интернет, либо в печатных изданиях строго запрещены. При нарушении данного правила, с нашей стороны будут предприняты соответствующие меры, вплоть до судебной жалобы.
© site-on.net
Шрифт: +стандартно-