WordPress & reCAPTCHA v2 – да пребудет с нами Сила!
Тип Поста

WordPress & reCAPTCHA v2 – да пребудет с нами Сила!

WordPress & reCAPTCHA v2 – да пребудет с нами Сила!

Ну что ж… вот и настал тот день, когда количество спама превысило мой уровень лени – пора сделать для своего сайта защиту от этих негодяев 🙂 И заодно описать весь процесс создания на примере WordPress-сайта и сервиса reCAPTCHA v2 от корпорации добра Google.

wordpress-recaptcha-gif-02

0. Подготовка

Итак, мы имеем сайт, работающий на WordPress и форму обратной связи, через которую регулярно приходит спам. Для примера будет использована стандартная тема Twenty Seventeen и чистый, только что скачанный WordPress версии 4.7.3. По большому счету, абсолютно не важна версия, да и какой движок используется для данной реализации защиты от спама. Отличия будут лишь в мелких деталях, а общий принцип останется неизменным.

Для начала скачаем предварительно подготовленные мной файлы feedback.php и functions.php из репозитория проекта по ссылке: https://github.com/sbogdanov108/wordpress_recaptcha/tree/00-Simple-form.

Эти файлы необходимо скопировать с заменой в папку темы wp-content/themes/twentyseventeen. Затем через админку WP нужно создать новую страницу и в Свойствах страницы -> Шаблон, выбрать feedback.

wordpress-recaptcha-00

На данный момент – это полностью рабочая форма обратной связи, но без защиты от спама. Именно реализацией этой защиты мы сейчас займемся.

1. Регистрация на сервисе reCAPTCHA

Чтобы зарегистрировать нашу собственную реКапчу, перейдем по ссылке https://www.google.com/recaptcha/admin и в блоке “Регистрация сайта” в поле “Название” введем любое удобное для нас имя, например, название нашего сайта. Затем выберем тип реКапчи “reCAPTCHA V2” и в поле “Домены” введем имя нашего сайта. Т.к. я использую локальный сервер, имя моего сайта будет localhost.

wordpress-recaptcha-01

2. Добавляем reCAPTCHA на сайт – сторона клиента

После того, как мы прошли регистрацию на сервисе reCAPTCHA, первым делом необходимо подключить в WP нужный JavaScript и добавить специальную разметку в HTML-код нашей формы. Сначала подключим JavaScript в WP.

Перейдем в файл twentyseventeen/functions.php и найдем функцию подключение скриптов function twentyseventeen_scripts() { ... }, в конец которой добавим код регистрации скрипта reCAPTCHA:

wp_enqueue_script('reCAPTCHA', 'https://www.google.com/recaptcha/api.js', array('jquery-scrollto'));

Но к этому скрипту так же нужно добавить дополнительные атрибуты async и defer. Сделать это можно с помощью хука script_loader_tag, который доступен с версии WP 4.1.0 специально для этих целей. Добавим в конец файла twentyseventeen/functions.php код:

function my_special_scripts($tag, $handle, $src) {
  if($handle === 'reCAPTCHA')
    return '<script src="' . $src . '" async defer></script>' . "\n";
  
  return $tag;
}
add_filter('script_loader_tag', 'my_special_scripts', 10, 3);

Теперь необходимо вставить в HTML-код нашей формы особую разметку:

<div class="g-recaptcha" data-sitekey="6Ldy6xwUAAAAAOQ0BDl6dtYFgBkpONcLquFkupMK"></div>

Обратите внимание, что data-sitekey у вас будет отличаться от моего, поэтому, вам нужно скопировать этот код со своей страницы настройки reCAPTCHA, из поля “Вставьте этот фрагмент в конце объекта <form> (там, где нужно разместить виджет reCAPTCHA)”.

wordpress-recaptcha-02

Там же находится секретный ключ, который нам понадобится позже.

Наша форма расположена в файле twentyseventeen/feedback.php, в котором нужно нужно заменить последний блок <div class="form-group"></div> в форме, чтобы он принял следующий вид:

<div class="form-group">
  <div class="col-sm-3">
    <input type="submit" class="btn btn-default" id="form-feedback-send" name="send" value="Отправить">
  </div>

  <div class="col-sm-9">
    <div class="g-recaptcha pull-right" 
         data-sitekey="6Ldy6xwUAAAAAOQ0BDl6dtYFgBkpONcLquFkupMK">
    </div>
  </div>
</div>

Этот код необходим всего лишь для того, чтобы reCAPTCHA отображалась более или менее красиво. Главная же часть, без которой ничего не произойдет, содержит всего лишь этот код:

<div class="g-recaptcha" data-sitekey="6Ldy6xwUAAAAAOQ0BDl6dtYFgBkpONcLquFkupMK"></div>

После всех проведенных манипуляций, reCAPTCHA должна появиться на странице. Теперь, после успешного прохождения пользователем этой капчи, на нашей странице появится скрытая текстовая зона, и её значение g-recaptcha-response будет передаваться вместе со всеми данными формы на сервер.

wordpress-recaptcha-03

Код состояния проекта на данном этапе разработки можно посмотреть по ссылке: https://github.com/sbogdanov108/wordpress_recaptcha/tree/01-Client-side.

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

3. Добавляем reCAPTCHA на сайт – сторона сервера

Теперь, когда пользователь решит капчу и нажмет кнопку “Отправить”, на сервер уйдут введенные им данные, а также значение g-recaptcha-response, которое было сгенерировано reCAPTCHA. Это значение нам нужно перехватить и отправить запрос на сервис reCAPTCHA для дополнительной проверки.

Запрос мы можем сделать обычными средствами PHP, но Гугл по доброте душевной специально для нас написал отдельную библиотеку именно для этих целей: https://github.com/google/recaptcha. Скачаем её, а затем поместим в директорию нашего шаблона twentyseventeen/libs/captcha файл autoload.php и папку ReCaptcha, которые находятся в скачанном архиве, в директории src.

wordpress-recaptcha-04

Теперь перейдем в шаблон feedback.php и в самом верху приведем код к следующему виду:

if ($_SERVER['REQUEST_METHOD'] === 'POST'
    && isset($_POST['send'])
    && isset($_POST['g-recaptcha-response']))
{
  $userSubject = $_POST['userSubject'];
  $userName = $_POST['userName'];
  $userEmail = $_POST['userEmail'];
  $userMessage = $_POST['userMessage'];
  $gReCaptcha = $_POST['g-recaptcha-response'];
  
  // Функция отправки почты, которая вернет false, если mail() не сможет отправить email
  // Или вернет массив с ошибками
  $result = feedback($userSubject, $userName, $userEmail, $userMessage, $gReCaptcha);
}

Обратите внимание, что мы добавили дополнительную проверку на наличие в POST-запросе поля g-recaptcha-response. Это отсеет не слишком смышленые спамерские скрипты, которые не умеют имитировать прохождение капчи. Но если все-же найдется такой скрипт, который добавит к своему POST-запросу поле g-recaptcha-response, то данные этого поля уйдут не проверку сервису reCAPTCHA и вот тут-то Гугл выведет его на чистую воду!

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

<div class="form-group">
  <div class="col-sm-3">
    <input type="submit" class="btn btn-default" id="form-feedback-send" name="send" value="Отправить">
  </div>

  <div class="col-sm-9">
    <div class="g-recaptcha-wrapper pull-right">
      <div class="g-recaptcha" data-sitekey="6Ldy6xwUAAAAAOQ0BDl6dtYFgBkpONcLquFkupMK"></div>
      <?= !empty($result['userCaptcha']) ? "<span class='help-block error'></span>" : '' ?>
    </div>
  </div>
</div>

Это позволит нам оповестить пользователя при наличии соответствующей ошибки.

Следующим шагом будет создание функции, которая обратится к сервису reCAPTCHA и проверит поле g-recaptcha-response. Для этого добавим в самый конец файла functions.php нашу функцию:

function callGoogle($gReCaptcha) {
  // Подключаем библиотеку для запроса к сервису
  require('libs/captcha/autoload.php');
  
  // Секретный ключ, который нужно получить на сервисе рекапчи
  $secretKey = 'ВАШ КЛЮЧ';
  
  $recaptcha = new \ReCaptcha\ReCaptcha($secretKey);
  $response = $recaptcha->verify($gReCaptcha); // Делаем запрос на сервис
  
  // Если запрос был успешно проверен
  if ($response->isSuccess())
    return true;
  
  return false;
}

Секретный ключ, который требуется для работы этой функции, нужно взять на сайте сервиса reCAPTCHA: https://www.google.com/recaptcha/admin.

Теперь необходимо вызвать созданную функцию и передать в неё поле g-recaptcha-response. Для этого всё в том же файле functions.php найдем функцию feedback() и добавим в неё немного кода:

function feedback($subject, $name, $userEmail, $message, $gReCaptcha) {
  $errors = [];
  // Наши данные, которые мы ввели в админке WordPress
  $adminEmail = get_bloginfo('admin_email');
  $siteName = get_bloginfo('name');
  
  // Проверяем капчу
  $checkCaptcha = callGoogle($gReCaptcha);
  
  if(!$checkCaptcha) {
    $errors['userCaptcha'] = 'Произошла ошибка при проверке капчи.';
  }
  // Далее идет код без изменений, поэтому тут он не приведен
}

Переменная $gReCaptcha содержит данные из нужного нам поля g-recaptcha-response, и эти данные мы передаем в созданную нами функцию callGoogle(), которая выполнит обращение к сервису reCAPTCHA и все необходимые проверки.

Ну что ж… Наша капча готова, код текущего состояния проекта можно посмотреть по ссылке: https://github.com/sbogdanov108/wordpress_recaptcha/tree/02-Server-side

4. Дорабатываем капчу

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

Для этих целей мы воспользуемся JavaScript API, которое по доброте душевной нам предоставляет Гугл. Полностью с API можно ознакомится по ссылке: https://developers.google.com/recaptcha/docs/display.

А пока мы будем использовать возможность вызова callback-функции, когда пользователь прошел капчу.

Вернемся в файл feedback.php и добавим к разметке капчи новый атрибут data-callback:

<div class="g-recaptcha" data-sitekey="6Ldy6xwUAAAAAOQ0BDl6dtYFgBkpONcLquFkupMK" data-callback="aiDaGugl"></div>

Значение этого атрибута и будет той функций, которая вызовется при условии прохождения пользователем капчи. Имя этой функции может быть любым, например, aiDaGugl. И еще добавим атрибут disabled для кнопки отправки формы, чтобы по умолчанию она была заблокирована:

<input type="submit" class="btn btn-default" id="form-feedback-send" name="send" disabled value="Отправить">

Теперь создадим файл в директории темы twentyseventeen/assets/js/captcha.js, в который добавим код нашей функции aiDaGugl():

function aiDaGugl() {
  // Удаляем атрибут disabled с кнопки отправки формы
  document.getElementById('form-feedback-send').removeAttribute('disabled');
}

И не забудем подключить этот скрипт в функции twentyseventeen_scripts() { ... } после скрипта reCAPTCHA:

wp_enqueue_script('captcha', get_theme_file_uri('/assets/js/captcha.js'), array('reCAPTCHA'));

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

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

Еще одно изменение, которое полезно будет сделать – реализовать подключение скриптов reCAPTCHA только на нужной нам странице. В данном случае, единственное место, где используется капча – это страница обратной связи. Зачем загружать эти скрипты на других страницах, если они там не используются? Давайте сделаем это!

5. Подключаем скрипты в WordPress только для одной страницы

Для этого перейдем в файл function.php и найдем функцию twentyseventeen_scripts() { ... }. Из этой функции удалим все скрипты, которые относятся к подключению капчи:

wp_enqueue_script('reCAPTCHA', 'https://www.google.com/recaptcha/api.js', array('jquery-scrollto'));
wp_enqueue_script('captcha', get_theme_file_uri('/assets/js/captcha.js'), array('reCAPTCHA'));

Затем перейдем в самый низ файла и добавим туда подключение скриптов по условию:

// Добавляем скрипты по условию
function add_my_script_where_it_necessery() {
  // Если это страница http://имя_сайта/feedback
  // Тогда подключаем нужные нам скрипты
  if(is_page('feedback'))
    add_action('wp_enqueue_scripts', 'my_scripts_method');
}
add_action('wp', 'add_my_script_where_it_necessery');

// Список скриптов
function my_scripts_method() {
  // reCAPTCHA
  wp_enqueue_script('reCAPTCHA', 'https://www.google.com/recaptcha/api.js', array('jquery-scrollto'));
  wp_enqueue_script('captcha', get_theme_file_uri('/assets/js/captcha.js'), array('reCAPTCHA'));
}

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

На этом наши приключения с Гуглом и его сервисом reCAPTCHA окончены, и мы получили то, что хотели – защиту от спамеров.

recaptcha-robot

Весь созданный нами код доступен в репозитории проекта.

При создании статьи были использованы следующие источники:

  1. reCAPTCHA Docs
  2. WordPress Docs
Поделиться

2 комментария

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

Вы можете использовать следующие HTML-теги:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Обязательно к заполнению