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.
Подпишитесь, чтобы раз в неделю получать свежие статьи с блога по email.

Смотрите также

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

  • sikor7 марта 2012 в 01:03 #

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

    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. Спасибо.

  • sikor7 марта 2012 в 07:03 #

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

  • Otshelnik-fm11 марта 2013 в 23:03 #

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

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

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

    • Миша12 марта 2013 в 03:03 #

      Спасибо))
      мой блок яндекс не очень любит) наверное из-за того, что большинство статей довольно короткие

      • Otshelnik-fm12 марта 2013 в 16:03 #

        Проиндексировано яндексом чуть меньше чем гуглом. А вот обратных ссылок дает яндекс на вас больше чем гугл. Так что кто еще кого не любит)).

        А вас нашел через гугл т.к. в техническом плане он лучше ищет.

        • Миша12 марта 2013 в 22:03 #

          ну я чисто по google analytics смотрю, с яндекса посещений ровно в два раза меньше, чем с гугла)

  • Александр16 июля 2013 в 21:07 #

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

  • Волшебник15 июня 2014 в 21:06 #

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

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

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

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

    • Миша16 июня 2014 в 06:06 #

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

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

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

  • Otshelnik-fm15 июня 2014 в 21:06 #

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

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

  • Волшебник16 июня 2014 в 15:06 #

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

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

  • Волшебник17 июня 2014 в 16:06 #

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

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

    • Миша17 июня 2014 в 16:06 #

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

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

  • Волшебник19 июня 2014 в 19:06 #

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

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

    • Otshelnik-fm19 июня 2014 в 20:06 #

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

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

  • Волшебник19 июня 2014 в 20:06 #

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

  • Jason28 ноября 2014 в 22:11 #

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

  • Волшебник11 февраля 2015 в 08:02 #

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

  • Волшебник18 февраля 2015 в 05:02 #

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

    • Миша18 февраля 2015 в 07:02 #

      Для ботов с постоянными адресами — да.

      Просто бомбить могут и вирусы с компов обычных пользователей + динамические IP-адреса никто не отменял)

  • Волшебник18 февраля 2015 в 08:02 #

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

    • Миша18 февраля 2015 в 08:02 #

      Ну да, если брать те IP-адреса, с которых приходит преимущественно только спам.

      Блин, тупые спамеры, неужели это приносит им хоть какой-то эффект??

      • Волшебник18 февраля 2015 в 09:02 #

        Ну как минимум спам могут использовать для быстрой индексации всякого мусора.
        Как максимум - бесплатные ссылки на заброшенных сайтах и форумах.

  • Роман llgr29 апреля 2015 в 03:04 #

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

    • Миша29 апреля 2015 в 10:04 #

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

      • Роман llgr30 апреля 2015 в 04:04 #

        Моя проблема связана с валидацией формы комментирования. Когда валидация появилась?)) как раз в 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

  • Эльдар18 мая 2015 в 23:05 #

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

  • Максим14 декабря 2015 в 20:12 #

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

  • Максим14 декабря 2015 в 21:12 #

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

    • Миша15 декабря 2015 в 13:12 #

      Можете по почте скинуть доступ к сайту?

      • Максим15 декабря 2015 в 13:12 #

        Решил проблему установкой плагина Antispam Bee - он работает по такому же принципу.

    • Роман23 декабря 2015 в 10:12 #

      Миша, ты не смотрел в чём проблема?
      WP 4.4 очень хочет чтобы заполняли именно такое поле:

      <textarea id="comment" name="comment"></textarea>
  • Максим23 декабря 2015 в 11:12 #

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

    • Миша23 декабря 2015 в 12:12 #

      Привет, на этой неделе постараюсь разобраться.

      • Владимир23 декабря 2015 в 20:12 #

        Тоже такая же хрень но только на сайте http://vzglyad.net.ua а вот на сайте http://smart-rabota.ru все нормально работает причем на обоих сайтах плагины примерно одинаковые различие только в темах .... посмотри будь добр что может быть ? вордпресс на обоих сайтах стоит 4.4

  • Максим23 декабря 2015 в 20:12 #

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

    • Владимир23 декабря 2015 в 20:12 #

      Сейчас попробую ....

    • Владимир23 декабря 2015 в 20:12 #

      Да проблема ушла заменой нового файла wp-comments-post.php на старый значит надо сравнить два файлика

      • Миша25 декабря 2015 в 16:12 #

        В общем да, пока что это единственный вариант.

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

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

        Что это значит? Ждём новую защиту от спама, а та, которая находится в этом посту, работает только до WP 4.4. Увы.

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

        • Владимир25 декабря 2015 в 16:12 #

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

          • Миша25 декабря 2015 в 16:12 #

            В WP полностью изменился wp-comments-post.php и его функции.

            • Владимир25 декабря 2015 в 16:12 #

              мистика какая то .....

              • Роман25 декабря 2015 в 16:12 #

                Покажи сайт на wp 4.4. где продолжает работать

                • Владимир25 декабря 2015 в 16:12 #

                  smart-rabota.ru на этом ни чего не откатывал

                  • Миша25 декабря 2015 в 16:12 #

                    Так у вас там и не стоит данного хука :) разве нет?

                    В общем постараюсь на праздниках соорудить какую-нибудь альтернативу.

                    • Владимир25 декабря 2015 в 16:12 #

                      обновлял все три сайта на автомате может что не обновилось ... а так ждем от вас альтернативу и С Наступающим всех !!!

                    • Роман25 декабря 2015 в 16:12 #

                      В общем с наступающим, парни)

                    • Миша26 декабря 2015 в 07:12 #

                      C Наступающим :)

  • VRS28 декабря 2015 в 03:12 #

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

    • Миша28 декабря 2015 в 08:12 #

      C Наступающим :) Да, хотелось бы поменьше))

    • Миша29 декабря 2015 в 06:12 #

      Обновил пост для версии 4.4. Большая просьба протестировать код, я не успеваю :)

      • Роман3 февраля 2016 в 15:02 #

        Миша, привет!
        Научи как можно заменить атрибут формы

        action

        на ссылку на файл antispam.php не через JavaScript?

        • Роман3 февраля 2016 в 18:02 #

          Ответ для functions.php:

          add_action( 'comment_form_before', 'my_comment_form_before' );
          function my_comment_form_before() {
          	ob_start();
          }
          add_action( 'comment_form_after', 'my_comment_form_after' );
          function my_comment_form_after() {
          	$html = ob_get_clean();
          	$html = preg_replace('/wp-comments-post.php/','antispam.php',$html);
          	echo $html;
          }

          Ну вроде способ защиты по-прежнему рабочий, да?

  • Анастасия6 февраля 2016 в 09:02 #

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

    • Миша8 февраля 2016 в 10:02 #

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

      • Анастасия8 февраля 2016 в 12:02 #

        Добрый день.

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

        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Просто код
  Для того, чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или авторизуйтесь на сайте.
Получайте новости блога по email или следите за мной в социальных сетях.
  • Миша: Метод тыка хорош, но оснвоы нужно знать в любом случае. Рекомендую почитать это.

  • Миша: Добрый вечер! Если я правильно понял, то: if( $opisanie ) echo '' . $opisanie . '' ;

  • alex morozov: Добрый вечер! у меня возникла следующая проблема. Я делаю фотоальбомы, чтобы они выглядели "как в контакте". Так вот, та...

  • Vladislav: Если эту муть убрать, то исчезает меню, и появляется описание под миниатюрами, которого не должно быть, как вы видите, я...

  • Миша: Либо размеры изображений вам помогут, либо CSS. И строку 14 гляньте, там муть какая-то.