Молодогвардейцев 454015 Россия, Челябинская область, город Челябинск 89085842764
MindHalls logo

Установка капчи для комментариев WordPress без плагинов

Доброго времени суток, дорогие друзья! Сессия закончилась, впереди небольшие каникулы. Жаль, но не успею я и духа перевести, как начнется следующий семестр. Не смотря на то, что времени заниматься сайтом практически не было, на свет недавно появился мой собственноручно написанный калькулятор шифра Цезаря, реализованный по алгоритму из одноименной статьи. Причин для его создания было две: невероятная популярность шифра Цезаря в интернете, и отсутствие калькуляторов с функцией взлома методом частотного анализа. Поэтому я решил внести свою лепту в эту историю.

Конец предыстории, вернемся к делу. Причиной написания этой статьи послужил ужасный спам в комментариях! За неделю мне приходилось удалять около сотни предложений купить всякий мусор. Логично, что я задумался о действительно серьезной капче на сайт, ставить ввод циферок очень не хотелось, кому нужно вводить циферки в 2016 году?

В голову пришла идея попробовать гугловскую «ReCaptcha». Подробнее о том, что это такое, и общий принцип ее установки вы можете прочитать в моей прошлой статье. А сейчас я разберу конкретный пример внедрения капчи для комментариев в WordPressе.

Весь процесс установки можно логически разбить на три шага.

  1. Добавить капчу к форме комментариев в HTML коде;
  2. Написать логику проверки капчи;
  3. Заставить WordPress сверять капчу каждый раз при добавлении комментария.

Пойдем по порядку.

Добавляем капчу к форме комментариев WordPress

Сначала нужно разобраться с отображением самой капчи в форме отправки комментария. Для этого немного подправим HTML код в файлике comments.php в папке с вашей темой. В 90% тем за отображение формы комментариев отвечает файл именно с таким названием. Ищем место, где создается и отрисовывается сама форма. Скорее всего, с помощью стандартной WP-функции comment_form(). Подробнее о том, как она работает вы можете прочитать в документации, там все доступно расписано.

Задача в том, чтобы добавить еще одно поле в аргументы этой функции. Если раньше вывод формы выглядел вот так.

$fields = array(
   'author' => '
<ul class="comment-form-ul">
<li class="comment-form-li"><span class="comment-form-author"><input type="text" id="author" name="author" class="author" value="' . esc_attr($commenter['comment_author']) . '" placeholder="Имя" pattern="[A-Za-zА-Яа-я]{3,}" maxlength="30" autocomplete="on" tabindex="1" required></span></li>

',
   'email' => '
<li class="comment-form-li"><span class="comment-form-email"><input type="email" id="email" name="email" class="email" value="' . esc_attr($commenter['comment_author_email']) . '" placeholder="E-mail" maxlength="30" autocomplete="on" tabindex="2" required></span></li>

',
   'url' => '
<li class="comment-form-li"><span class="comment-form-url"><input type="url" id="url" name="url" class="site" value="' . esc_attr($commenter['comment_author_url']) . '" placeholder="Сайт" maxlength="30" tabindex="3" autocomplete="on"></span></li>
</ul>

'
 );

 $args = array(
  'fields' => apply_filters('comment_form_default_fields', $fields),
  'comment_notes_after' => '',
  'comment_notes_before' => 'Ваш E-mail не будет опубликован.
 Вы можете добавить исходный код, заключив его в.',
  'comment_field' => '

<textarea id="comment" name="comment" class="comment-form" cols="45" rows="4" aria-required="true" placeholder="Текст сообщения..."></textarea>

',
  'label_submit' => 'Отправить'
  
);

comment_form($args);

 

Сейчас мы добавим в массив $fields еще один элемент 'captcha' => '<div class="g-recaptcha" data-sitekey="ВАШ_КЛЮЧ"></div>'. Не забудьте вставить свой открытый API-ключ. Вот пример с моим ключом.

$fields = array(
   'author' => '
<ul class="comment-form-ul">
<li class="comment-form-li"><span class="comment-form-author"><input type="text" id="author" name="author" class="author" value="' . esc_attr($commenter['comment_author']) . '" placeholder="Имя" pattern="[A-Za-zА-Яа-я]{3,}" maxlength="30" autocomplete="on" tabindex="1" required></span></li>

',
   'email' => '
<li class="comment-form-li"><span class="comment-form-email"><input type="email" id="email" name="email" class="email" value="' . esc_attr($commenter['comment_author_email']) . '" placeholder="E-mail" maxlength="30" autocomplete="on" tabindex="2" required></span></li>

',
   'url' => '
<li class="comment-form-li"><span class="comment-form-url"><input type="url" id="url" name="url" class="site" value="' . esc_attr($commenter['comment_author_url']) . '" placeholder="Сайт" maxlength="30" tabindex="3" autocomplete="on"></span></li>
</ul>

',
   'captcha' => '
<div class="g-recaptcha" data-sitekey="6LeauRAUAAAAAN0WLUvBCqTFBWmqRDQcpjfu2w6c"></div>

'
 );

 $args = array(
  'fields' => apply_filters('comment_form_default_fields', $fields),
  'comment_notes_after' => '',
  'comment_notes_before' => 'Ваш E-mail не будет опубликован.
 Вы можете добавить исходный код, заключив его в code /code.',
  'comment_field' => '

<textarea id="comment" name="comment" class="comment-form" cols="45" rows="4" aria-required="true" placeholder="Текст сообщения..."></textarea>

',
  'label_submit' => 'Отправить'
  
);

comment_form($args);

Отлично, капча появилась в форме комментариев, но сейчас она "мертва", давайте вдохнем в нее душу.

Пишем функцию проверки капчи

Лучше всего вынести непосредственно проверку капчи в отдельную функцию в файле funtions.php вашей темы и воспользоваться хуком WordPressа под названием pre_comment_on_post. Смысл заключается в том, что наш код отработает сразу перед занесением комментария в базу и проследит за тем, чтобы в базу отправились только те комментарии, капча которых успешно пройдена.

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

<?php
/*
* (c) Кузьминых Кирилл 06.01.2017
*/

//Проверка капчи от гугла
function recaptchaCheck() {
    $recaptcha = $_POST['g-recaptcha-response'];
    
    if(!empty($recaptcha)) {
        $recaptcha = $_REQUEST['g-recaptcha-response'];
        $secret = '6LeauRAUAAAAAFuWlYJYTQdtipOJQVnQdkE-LvkC';
        $url = "https://www.google.com/recaptcha/api/siteverify?secret=".$secret ."&response=".$recaptcha."&remoteip=".$_SERVER['REMOTE_ADDR'];

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16");
        $curlData = curl_exec($curl);

        curl_close($curl);  

        $curlData = json_decode($curlData, true);

        if($curlData['success']) {
            return;
        } else {
            $location = get_page_link($comment_post_ID);
            wp_safe_redirect($location);
            exit;
        }
    }
    else {
        $location = get_page_link($comment_post_ID);
        wp_safe_redirect($location);
        exit;
    }
}

Заставляем WordPress проверять капчу при добавлении комментария

Раньше здесь была очень сложная инструкция по редактированию файлов самой CMS WordPress. Огромным минусом такого подхода, как заметил в комментариях добрый человек по имена Павел, при обновлении WP наши труды канут в лету. Поэтому мы и воспользуемся системной хуков, которая очень кстати для того и придумана. Заставить WordPress проверить нашу капчу перед публикацией комментария можно всего одной строчкой, которая должна быть написана в файле functions.php сразу после функции recaptchaCheck.

add_action('pre_comment_on_post', 'recaptchaCheck');

Где первым аргументом является хук, к которому мы цепляемся, а вторым наша функция проверки капчи.

Заключение

Я противник плагинов по многим причинам, и как можно больше стараюсь устанавливать руками. Это помогает понять принцип работы той или иной вещи, и быть уверенным в том, что поддержка не прекратится, и не придется искать плагин-замену. Поэтому и капчу на комментарии для WordPress`а я устанавливал сам. Кроме того, это было очень интересно и познавательно. Спасибо за внимание!

  • Хороший способ. Плагины — зло, поддерживаю))
    Могу только посоветовать не переписывать файл wp-comments-post.php, который WP снова перепишет при обновлении. Лучше добавить в functions.php хук

    add_action( 'pre_comment_on_post', 'action_recaptchaCheck' );
    function action_recaptchaCheck( $comment_post_ID ){
    	// action...
    }

    Который сработает в функции wp_handle_comment_submission() перед добавлением комментария в базу, как видно из названия хука.

    Кстати, меня самого недавно спам одолел. Антиспам плагин отфильтровывает в день до 700 сообщений спама! Началось после 20 января

    • Кирилл Кузьминых

      Да, это гораздо лучше, чем переписывать файлик, спасибо! А я по началу руками весь спам удалял, вот потеха была

      • Могу представить. Тоже иногда приходится удалять спам-комментарии целыми страницами