100% защита от автоспама в комментариях

Начну с того, что покажу скриншот того, что творилось на одном из моих блогов ещё в конце прошлого года.

пример автоспама админка wordpress

Трудно поверить, верно?

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

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

Полный бред.

Так как все эти комменты оставляют боты, то их легко можно обмануть.
Бот заточен под WordPress? — значит надо сделать форму комментариев, не похожую на стандартную вордпрессовскую.

<form method="POST" name="commentform">
	<input type="text" name="author" id="author" />
	<input type="text" name="email" id="email" />
	<textarea name="comment" id="comment"></textarea>
</form>

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

	<textarea name="comment" id="comment"></textarea><!-- фейк -->
	<textarea name="true_comment"></textarea><!-- настоящее -->

Теперь надо, чтобы WordPress понимал, какое поле настоящее, а какое нет и в случае чего давал пенделя кому следует. Этот код — в functions.php

function stop_spam($commentdata) {
	$fake = trim($_POST['comment']);
	if(!empty($fake)) wp_die('Ошибка!');
		$comment_content = trim($_POST['true_comment']);
	$_POST['comment'] = $comment_content;	
	return $commentdata;
}
 
add_filter('pre_comment_on_post', 'stop_spam');

Ах да, ведь теперь же у нас два поля для ввода комментария 🙂
Заюзаем CSS.

#comment{
	position:absolute;
	left:-9000px;
}

Функция comment_form()

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

Что делать, если она используется на вашем блоге? Нужно в functions.php добавить ещё кое-что (то, что мы добавляли раньше, удалять не нужно).

function edit_comment_form_fields($default) {
	$commenter = wp_get_current_commenter();
	$default['comment_notes_after'] .= 
	'<p class="comment-form-true_comment">
	<label for="true_comment">Ваш комментарий:</label>
	<textarea id="true_comment" name="true_comment" rows="8" cols="45" aria-required="true"></textarea>
	</p>';
	return $default;
}
 
add_filter('comment_form_defaults', 'edit_comment_form_fields');

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

Почему перестала работать защита от спама с подменой полей в WordPress 4.4 и как это исправить?

В WP 4.4 изменился код файла wp-comments-post.php, находящегося в корне вашего сайта, таким образом, что наш хук pre_comment_on_post запускается слишком поздно и уже не успевает выполнять свою функцию. Альтернативы в виде хуков я не нашёл, поэтому представляю вам другое, также весьма простое решение.

  1. Если у вас ещё используется хук из предыдущего шага, удалите его.
  2. В корне сайта создайте файл с произвольным названием, например antispam.php и поместите туда следующий код:
    <?php
    $fake = trim($_POST['comment']);
    if(!empty($fake))
    	exit;
    $_POST['comment'] = trim($_POST['true_comment']);
     
    require( dirname(__FILE__) . '/wp-comments-post.php' );
  3. Замените атрибут формы action на ссылку на этот файл (antispam.php). Если вы используете comment_form() для вывода формы, то замену проще всего сделать через JavaScript.

Миша Рудрастых

Впервые познакомился с WordPress в 2009 году. С 2014 года меня можно встретить на WordCamp — официальной конфе по WordPress, иногда там выступаю. Также в настоящее время веду курсы по WordPress в Epic Skills.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля — пишите мне.

Комментарии 66

  • sikor:

    Все получилось. Как я понял, если использовать форму комментариев из этого поста, то можно не использовать код

    function stop_spam($commentdata) {
        $fake = trim($_POST['comment']);
        if(!empty($fake)) wp_die('Ошибка!');
            $comment_content = trim($_POST['true_comment']);
        $_POST['comment'] = $comment_content;
        return $commentdata;
    }
     
    add_filter('pre_comment_on_post', 'stop_spam');

    - форма комментариев остается пустой и спам не отправляется.
    Удалил плагин Antispam Bee. Спасибо.

  • sikor:

    Побольше бы таких постов о замене плагинов на код.

  • Странно что я не находил ваш блог в рунете. Случайно попал на него сегодня и остаюсь!

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

    Спасибо за сайт. Буду следить за вами )))

  • Александр:

    Изящное решение. WP не перестает удивлять.

  • Волшебник:

    Интересное решение. У меня несколько вопросов по этому.

    1. Допустим мне не нужно в форме комментариев поле с адресом сайта. Как его можно тоже задействовать в дополнение к этому решению? Например скрыть это поле средствами CSS и если оно заполнено, то удалять такие комменты сразу. Или этого не требуется и основной способ с одним полем срабатывает всегда 100%?

    2. При данном способе всё отсеянное улетает в папку "спам" или удаляется сразу? Хотелось бы чтобы удалялось сразу.

    3. Можете посоветовать какой-нибудь плагин, делающий то же самое? Т.к. при наличии множества тем оформления, вносить изменения в каждую немного проблематично.

    • Миша:

      1. Если поле сайта не нужно, его лучше удалить (через PHP, но никак не через CSS). Да, 100% против автоспама.

      2. Не добавляется вообще, как написал @Otshelnik-fm ниже, WordPress прервет обработку и коммент не добавится в базу - а значит не будут потрачены ресурсы сервера.

      3. Плагинов подобного рода не встречал. Ну тут в принципе нетрудно написать его самому.

  • Otshelnik-fm:

    Волшебник привет.
    Этот способ работает 100% и не обязательно удалять поле сайта.
    wp_die('Ошибка!') - показывает, что спамеру будет показываться чистый лист с единственной надписью, а сам комментарий не пройдет в базу данных - т.к. вордпресс прервет обработку. В итоге нет в админке помеченных спамом записей. Там будет чисто.

    На днях вот еще один свой сайт перевел на этот метод, когда за сутки спамом написали 2000 комментариев и хостер прислал сообщение о перегрузке сервера. Заняло минут 10 все изменения. Теперь всё чисто и только люди ручками могут оставить свой комментарий.
    А за год использования на другом сайте автоботы не прошли))

  • Волшебник:

    Если тема использует стандартный код вызова, вида comment_form(), то проблем нет. Однако некоторые темы модифицируют форму отправки коммента. Что делать, если код вызова комментариев (в comments.php) например такой:

    comment_form(array('comment_notes_after' => '', 'title_reply' => __('Leave a comment','themead')));

  • Волшебник:

    В общем всё настроил, отключил акисмет, посмотрим на результаты. Акисмет в принципе не пропускает спам-комментарии, но раздражает, что некоторый спам он всё равно складывает в папку "спам", а не удаляет сразу.

    А почему бы ложное поле не скрыть в display:none? Или боты просекут?

    • Миша:

      Akismet коварный, он может так базу данных забить, что мало не покажется.

      Думаю можно и через display: none;. Относительно того, просекут или нет - вроде не просекают, у меня раньше так стояло.

  • Волшебник:

    Отличный метод. До сих пор ни одного спама не прошло )
    Думаю, если сюда добавить рандомный код вместо одного и того же id="true_comment", чтобы всегда менялось и нельзя было привыкнуть и еще одно поле, то будет 200% защита от спама.

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

    • Otshelnik-fm:

      так вы прям id=”true_comment” и вписали? 🙂
      я указал свой уникальный. как только хоть один спамбот его разгадает - поменяю на другой неповторимый id

      Усложнять функцию не надо - у меня больше чем за год использования функции мой id стоит и не разгадали. Всё работает как часы.

  • Волшебник:

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

  • Jason:

    У меня почему-то не работает 🙁
    Использую твои аякс-комменты, а так же оба хука из этой статьи. При заполнение фейкового(name=comment) поля даёт ошибку, а при заполнении правильного(name=true_comment) требует заполнить фейковое...

  • Волшебник:

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

  • Волшебник:

    Прикрутил к форуму импровизированный php скрипт. Боты больше не проходят.
    У меня еще такая мысль появилась - получаем IP адрес заполнившего ложное поле и добавляем его в .htaccess в список deny from, и навеки прощаемся с ботом. Ведь хоть коменты то не проходят, но эти же самые боты всё равно продолжают бомбить ежедневно сайт по много раз. Например я в логах насчитал за сутки более 50 заполнивших ложные поля, из них 95% прилетают с одного-двух ip адресов и они посещают сайт каждый день.
    Можно так же туда вносить всех, то пытается лезть в запрещенные адреса.
    Пример реализации gist.github.com/dimlife/5799050

  • Волшебник:

    Ну... можно вести учёт, например записывать лог за сутки, в конце суток, самый активный адрес с которого идёт спам, блокировать навсегда в htacess. Таким образом мы на автомате отсекаем бОльшую часть самых активных ботов, с которых валится 90% спама.

  • Роман llgr:

    Я обновился до wp 4.2.1. и отправка комментариев через созданное поле перестала работать.
    Если убрать доп.поле и отправлять через обычный textarea - то всё ок.
    Нужно как-то изменить код?

    • Миша:

      Хм, у меня вроде всё работает на wp 4.2.1.

      • Роман llgr:

        Моя проблема связана с валидацией формы комментирования. Когда валидация появилась?)) как раз в 4.2.1? вообще размер исходного файла /wp-includes/comment-template.php подрос с последним обновлением. Я так и не понял.
        Консоль отдаёт ошибку "An invalid form control with name='comment' is not focusable." Естественно форма с name='comment' спрятана за display:none; а отправлять я пытаюсь свою name='llgr-comment'.
        Если в лоб к

        <form>

        добавить novalidate, тогда всё отлично отправляется. Как через functions.php добавить это novalidate я не придумал. Да и правильно ли так делать?

        Моя страница, если будете смотреть http://dogshow.me/blog/kakoy-vyistavochnyiy-povodok-ringovku-kupit

  • Эльдар:

    После обновления wp 4.2.1 защита перестала работать , комментарии не отправляются.

  • Максим:

    После обновления wp до версии 4.4 защита перестала работать , комментарии не отправляются. Как можно починить?

  • Максим:

    Пишет: ОШИБКА: пожалуйста, введите комментарий.

  • Максим:

    Привет после обновления вордпресс тоже не работает форма отправки комментария пишет ОШИБКА: пожалуйста, введите комментарий. Решите пожалуйста проблему мой блог seoslim.ru

  • Максим:

    Привет, пока проблему решил следующим образом, заменил в корне сайта обновленный файл wp-comments-post.php на старый, что был до обновления и проблема ушла. Но это не выход, каждый раз править файлы.

  • VRS:

    Спасибо, Миша.
    Твой блог как всегда помогает держать руку на пульсе, а то я бы еще неизвестно сколько времени бродила в поисках ответа, почему не работает pre_comment_on_post.
    С наступающим Новым годом!
    Поменьше бы нам таких неприятных сюрпризов в нем).

  • Анастасия:

    Миша, добрый день.
    А если с хука pre_comment_on_post перевесить на пораньше, например, init, то заработает и старый вариант

    • Миша:

      Добрый день!
      Буду благодарен за пример. Не помню почему, но вроде у меня что-то не получалось с pre_comment_on_post.

      • Анастасия:

        Добрый день.

        Вот вы пишите: "наш хук

        pre_comment_on_post

        запускается слишком поздно и уже не успевает выполнять свою функцию"

        Вместо

        pre_comment_on_post

        берем

        init

        , например, который запускается значительно раньше.

        У меня нормально работает вот такой код:

        add_filter( 'comment_form_defaults', 'antispam_comment_form_textarea' );
        function antispam_comment_form_textarea( $defaults ) {
        	 $defaults['comment_field'] = '<p class="comment-form-comment"><label for="comment">Ваш комментарий</label><textarea id="comment" style="display: none;" name="comment"></textarea><textarea id="real-comment" name="real-comment" cols="45" rows="8" aria-describedby="form-allowed-tags" aria-required="true"></textarea></p>';
        	$defaults['comment_notes_after'] = '';
          	$defaults['title_reply'] = __( 'Поделитесь своими мыслями' );
        	return $defaults;
        }
         
        // Защита от спама в комментариях
        add_filter('init', 'verify_spam');
        function verify_spam($commentdata) {
              $spam_test_field = trim($_POST['comment']);
          if(!empty($spam_test_field)) wp_die('Спаму нет!');
              $comment_content = trim($_POST['real-comment']);
              $_POST['comment'] = $comment_content;
          return $commentdata;
        }

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

phpjsHTMLCSSSQLПросто код
  Комментарии закрыты.