Интеграция CAPTCHA в форму регистрации WordPress

В этой статье мы создадим плагин, который на этот раз будет интегрировать CAPTCHA (Google reCAPTCHA) с формой регистрации WordPress по умолчанию. Конечно, HTTP API будет использоваться для связи с ReCaptcha для проверки ответа, предоставляемого пользователем на запрос CAPTCHA.

Ниже приведен скриншот формы регистрации, защищенной CAPTCHA для предотвращения спам-регистраций:

Для чего интегрировать CAPTCHA в форму регистрации?

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

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

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

Одним из проверенных и надежных способов снижения а, возможно, и полного устранения спама, является реализация в веб-формах CAPTCHA.

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

Благодаря интеграции CAPTCHA в форму регистрации WordPress, спам-регистрации скоро станут для вас лишь воспоминаниями из прошлого.

Разработка плагина

Прежде чем мы начнем составлять код плагина, давайте зайдем на reCAPTCHA, зарегистрируем ваше доменное имя и возьмем ваши public и private API-ключи.

Во-первых, включаем заголовок плагина:

<?php

/*
Plugin Name: reCAPTCHA in WP Registration Form
Plugin URI: http://sitepoint.com
Description: Add Google's reCAPTCHA to WordPress registration form
Version: 1.0
Author: Agbonghama Collins
Author URI: http://w3guy.com
License: GPL2
*/

Создаем класс PHP с двумя свойствами, в которых будут храниться ваши приватный и публичный ключи:

class Captcha_Registration_Form {

    /** @type string private key|public key */
    private $public_key, $private_key;

Метод конструктора плагина будет состоять из двух обращений действий, которые будут добавлять вопросы CAPTCHA в форму регистрации и проверять ответы на них:

/** конструктор класса */
    public function __construct() {
        $this->public_key  = '6Le6d-USAAAAAFuYXiezgJh6rDaQFPKFEi84yfMc';
        $this->private_key = '6Le6d-USAAAAAKvV-30YdZbdl4DVmg_geKyUxF6b';

        // добавляет captcha в форму регистрации
        add_action( 'register_form', array( $this, 'captcha_display' ) );

        // аутентифицирует ответ captcha
        add_action( 'registration_errors', array( $this, 'validate_captcha_field' ), 10, 3 );
    }

Метод captcha_display(), который будет выводить reCAPTCHA, добавляется в форму регистрации WordPress через действие register_form.

Метод validate_captcha_field(), который проверяет, что: поле CAPTCHA заполнено, а также проверяет ответ, предоставленный пользователем, - добавляется в систему проверки регистрации действием registration_errors.

Ниже приведен код методов captcha_display() и validate_captcha_field(), о которых я только что рассказал:

/** Вывод поля формы reCAPTCHA. */
    public function captcha_display() {
        ?>
        <script type="text/javascript"
                src="http://www.google.com/recaptcha/api/challenge?k=<?=$this->public_key;?>">
        </script>
        <noscript>
            <iframe src="http://www.google.com/recaptcha/api/noscript?k=<?=$this->public_key;?>"
                    height="300" width="300" frameborder="0"></iframe>
            <br>
            <textarea name="recaptcha_challenge_field" rows="3" cols="40">
            </textarea>
            <input type="hidden" name="recaptcha_response_field"
                   value="manual_challenge">
        </noscript>

    <?php
    }
	/**
     * Проверка ответа captcha
     *
     * @param $user строка имя пользователя
     * @param $password строка пароль
     *
     * @return WP_Error|WP_user
     */
    public function validate_captcha_field($errors, $sanitized_user_login, $user_email) {

        if ( ! isset( $_POST['recaptcha_response_field'] ) || empty( $_POST['recaptcha_response_field'] ) ) {
            $errors->add( 'empty_captcha', '<strong>ERROR</strong>: CAPTCHA should not be empty');
        }

        if( $this->recaptcha_response() == 'false' ) {
            $errors->add( 'invalid_captcha', '<strong>ERROR</strong>: CAPTCHA response was incorrect');
        }

        return $errors;
    }

Обратите внимание на validate_captcha_field(), особенно на второй оператор условия if, вызов осуществляется для recaptcha_response(), чтобы проверить правилен ли ответ, предоставленный пользователем (возвращается false, если ответ неверный).

Давайте рассмотрим код и пояснения к нему для recaptcha_response():

/**
     * Получаем ответ reCAPTCHA API.
     *
     * @return string
     */
    public function recaptcha_response() {

        // Данные вопроса reCAPTCHA
        $challenge = isset($_POST['recaptcha_challenge_field']) ? esc_attr($_POST['recaptcha_challenge_field']) : '';

        // Данные ответа reCAPTCHA
        $response  = isset($_POST['recaptcha_response_field']) ? esc_attr($_POST['recaptcha_response_field']) : '';

        $remote_ip = $_SERVER["REMOTE_ADDR"];

        $post_body = array(
            'privatekey' => $this->private_key,
            'remoteip'   => $remote_ip,
            'challenge'  => $challenge,
            'response'   => $response
        );

        return $this->recaptcha_post_request( $post_body );

    }

Пояснение кода: Чтобы убедиться, что ответ CAPTCHA, предоставленный пользователем является правильным, отправляется POST-запрос к конечной точке http://www.google.com/recaptcha/api/verify со следующими параметрами:

  • privatekey - ваш секретный ключ;
  • remoteip - IP-адрес пользователя, который отвечал на вопрос CAPTCHA;
  • challenge - значение recaptcha_challenge_field, переданное через форму;
  • response - значение recaptcha_response_field, переданное через форму.

Во-первых, POST-данные вопроса и ответа, отправленные через форму, захватываются и сохраняется в $challenge и $response соответственно.

IP-адрес пользователя захватывается через $_SERVER["REMOTE_ADDR"] и сохраняется в $remote_ip.

Для отправки POST-запроса с HTTP API, параметры или тело должны быть представлены в виде массива, как это показано ниже:

$post_body = array(
            'privatekey' => $this->private_key,
            'remoteip'   => $remote_ip,
            'challenge'  => $challenge,
            'response'   => $response
        );

Параметры POST передаются в качестве аргумента к recaptcha_post_request (), который затем отправляет запрос с параметрами по адресу https://www.google.com/recaptcha/api/verify и возвращает ответ API.

recaptcha_post_request() возвращает true, если ответ на вопрос CAPTCHA верен, в противном случае - false.

Ниже приводится код recaptcha_post_request():

/**
     * Отправка запроса HTTP POST и возвращение результата.
     *
     * @param $post_body массив тела HTTP POST
     *
     * @return bool
     */
    public function recaptcha_post_request( $post_body ) {

        $args = array( 'body' => $post_body );

        // отправляем POST-запрос к Google reCaptcha Server
        $request = wp_remote_post( 'https://www.google.com/recaptcha/api/verify', $args );

        // получаем тело ответа на запрос
        $response_body = wp_remote_retrieve_body( $request );

        /**
         * разбиваем тело ответа и используем request_status
         * @see https://developers.google.com/recaptcha/docs/verify
         */
        $answers = explode( "n", $response_body );

        $request_status = trim( $answers[0] );

        return $request_status;
    }

Пояснение кода: массив $args с телом POST $post_body сохраняется в созданный ключ body.
wp_remote_post отправляет POST-запрос с ответом, сохраняемым в $request.

Тело ответа извлекается через wp_remote_retrieve_body и сохраняется в $response_body.

Если проверка CAPTCHA была пройдена, reCAPTCHA API возвращает:

true
success

В противном случае возвращается следующая ошибка:

false
incorrect-captcha-sol

Чтобы метод recaptcha_post_request возвращал логическое значение (true в случае успешного прохождения проверки и false, если наоборот); ответ $response_body разбивается, и данные массива с индексами 0 обрезаются, чтобы удалить лишние пробелы в начале и в конце строк.

В конце мы закрываем класс плагина:

} // Captcha_Registration_Form

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

new reCAPTCHA_Login_Form();

Заключение

Если вы хотите использовать этот плагин на своем WordPress сайте или изучить его код, скачайте плагин из хранилища на GitHub.

Успехов в работе!

РедакцияПеревод статьи «Integrating a CAPTCHA with the WordPress Registration Form»