WordPress. Защита страницы авторизации

03.06.2019

Теги: CMSWeb-разработкаWordPressАвторизацияПлагинФорма

Страница авторизации — одно из слабых мест WordPress. После публикации сайта роботы будут постоянно пытаться получить доступ к сайту. А сам WordPress им будет в этом помогать. При вводе неправильного логина, WP выдает сообщение «Неверное имя пользователя». При вводе неправильного пароля — сообщение будет «Введённый вами пароль пользователя … неверен». Т.е. WordPress подсказывает злоумышленнику, что он делает неправильно.

Давайте создадим плагин, который будет изменять все сообщения об ошибках на одно — «Ошибка авторизации». И добавим простую проверку на робота — checkbox «Я не робот», который надо отметить, чтобы авторизоваться.

Итак, создаем директорию tokmakov-auth-captcha, а внутри нее — файл tokmakov-auth-captcha.php:

<?php
/*
Plugin Name: Дополнительная защита для страницы авторизации
Plugin URI: https://tokmakov.msk.ru
Description: Добавляет проверку на робота и изменяет сообщение об ошибке
Version: 1.0
Author: Евгений Токмаков
Author URI: https://tokmakov.msk.ru
*/

Изменяем сообщение об ошибке:

add_filter('login_errors', function ($errors) {
    $errors = 'Ошибка авторизации';
    return $errors;
});

Добавляем checkbox «Я не робот»:

add_action('login_form', function () {
    ?>
    <p class="auth-captcha">
        <label for="captcha">
            <input type="checkbox" name="captcha" id="captcha" value="1">
            Я не робот
        </label>
    </p>
    <?php
});

Проверка на робота, первый способ

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

add_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
add_filter('authenticate', 'wp_authenticate_email_password',    20, 3);

Мы можем привязать к этому событию свою функцию, и в ней проверить — был ли отмечен checkbox «Я не робот»:

add_filter(
    'authenticate',
    function ($user, $username, $password) {
        // проверяем, что checkbox «Я не робот» был отмечен
    }
    30,
    3
);

Наша функция принимает три параметра — $user, $username, $password. Первый параметр может быть null, WP_User или WP_Error. Функция должна вернуть:

  • null — означает, что проверки еще не было
  • WP_User — означает, что проверка пройдена
  • WP_Error — означает, что проверка не пройдена

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

  • wp_authenticate_username_password()
  • wp_authenticate_email_password()

У этих функций приоритет равен 20. Если мы зададим приоритет 10 — наша функция будет вызвана раньше, если зададим приоритет 30 — наша функция будет вызвана позже. Если приоритет 10 — первый параметр будет null, потому что наша проверка — первая. Если приоритет 30 — первый параметр будет объектом WP_User или WP_Error, который вернут эти две функции.

add_filter(
    'authenticate',
    function ($user, $username, $password) {

        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            return $user;
        }

        // если уже произошла ошибка — больше ничего не делаем
        if (is_wp_error($user)) {
            return $user;
        }

        // проверяем, что checkbox «Я не робот» был отмечен
        if (!isset($_POST['captcha'])) {
            $error = new WP_Error(
                'failed_user_auth',
                'Ошибка авторизации'
            );
            return $error;
        }
        return $user;
    },
    30,
    3
);

Проверка на робота, второй способ

Перед получением окончательного результата авторизации WordPress запускает фильтр wp_authenticate_user для добавления дополнительного этапа проверки. Здесь мы можем проверить, является ли пользователь человеком или роботом. Если это человек, мы возвращаем объект пользователя, в противном случае — возвращаем объект ошибки.

add_filter(
    'wp_authenticate_user',
    function ($user, $password) {
        // если уже произошла ошибка — больше ничего не делаем
        if (is_wp_error($user)) {
            return $user;
        }
        // проверяем, что checkbox «Я не робот» был отмечен
        if (!isset($_POST['captcha'])) {
            $error = new WP_Error(
                'failed_user_auth',
                'Ошибка авторизации'
            );
            return $error;
        }
        return $user;
    },
    10,
    2
);

Вместо заключения

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

add_filter('login_errors', function ($errors) {
    $errors = 'Ошибка авторизации';
    return $errors;
});

Чтобы сообщение об ошибке всегда было «Ошибка авторизации» — заменяем объект WP_Error, созданный WordPress:

add_filter(
    'authenticate',
    function ($user, $username, $password) {
        /*...*/
        // если уже произошла ошибка — больше ничего не делаем
        if (is_wp_error($user)) {
            $error = new WP_Error(
                'failed_user_auth',
                'Ошибка авторизации'
            );
            return $error;
        }
        /*...*/
    },
    30,
    3
);
add_filter(
    'wp_authenticate_user',
    function ($user, $password) {
        /*...*/
        // если уже произошла ошибка — больше ничего не делаем
        if (is_wp_error($user)) {
            $error = new WP_Error(
                'failed_user_auth',
                'Ошибка авторизации'
            );
            return $error;
        }
        /*...*/
    },
    10,
    2
);

Поиск: CMS • Web-разработка • WordPress • Авторизация • Плагин • Форма • Пароль • Password • Authenticate

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.