Создание и использование автоматического OTP для входа в WordPress без плагинов

Диагностика проблемы: зачем нужен автоматический OTP на странице входа

Стандартная форма входа WordPress уязвима к атакам перебора паролей (brute force) и фишинговым схемам. Добавление одноразового пароля (OTP) — эффективный способ повысить безопасность, но большинство готовых решений требуют установки плагинов, что не всегда приемлемо по причинам производительности или совместимости. В этом руководстве рассмотрим, как реализовать OTP-систему для входа на wp-login.php самостоятельно, используя собственный код.

Подготовка: какие данные нужны и как хранить OTP

Для генерации и проверки OTP нам потребуются:

  • Генерация временного кода (6 цифр).
  • Хранение временного кода и времени его жизни.
  • Отправка кода пользователю (например, на email, SMS — для примера рассмотрим email).
  • Валидация кода при входе.

Рекомендуется хранить OTP в user_meta с указанием времени создания, чтобы ограничить срок действия (например, 5 минут).

Пошаговое решение: реализация OTP без плагинов

1. Генерация и отправка OTP при вводе логина и пароля

Добавим проверку пароля, а вместо стандартного входа — генерацию кода и отправку его на email пользователя.

add_filter('authenticate', 'custom_authenticate_with_otp', 30, 3);
function custom_authenticate_with_otp($user, $username, $password) {
    if (empty($username) || empty($password)) {
        return $user;
    }

    $user = get_user_by('login', $username);
    if (!$user || !wp_check_password($password, $user->user_pass, $user->ID)) {
        return new WP_Error('authentication_failed', __('Неверный логин или пароль.'));
    }

    // Генерируем OTP
    $otp = rand(100000, 999999);
    update_user_meta($user->ID, 'login_otp_code', $otp);
    update_user_meta($user->ID, 'login_otp_time', time());

    // Отправляем OTP на email
    wp_mail($user->user_email, 'Ваш одноразовый пароль для входа', 'Код: ' . $otp . '\nСрок действия 5 минут.');

    // Сообщаем, что нужен OTP
    return new WP_Error('otp_required', __('Введите одноразовый пароль, отправленный на ваш email.'));
}

2. Добавление поля для ввода OTP на форму входа

Выведем дополнительное поле на страницу входа для ввода кода.

add_action('login_form', 'add_otp_field_to_login_form');
function add_otp_field_to_login_form() {
    $value = isset($_POST['login_otp']) ? esc_attr($_POST['login_otp']) : '';
    echo '<p><label for="login_otp">Одноразовый пароль (OTP)<br></label>';
    echo '<input type="text" name="login_otp" id="login_otp" class="input" value="' . $value . '" size="20" /></p>';
}

3. Проверка OTP при повторной отправке формы

Если ошибка otp_required была выдана, при повторной отправке формы проверяем введённый код.

add_filter('authenticate', 'check_otp_after_password', 40, 3);
function check_otp_after_password($user, $username, $password) {
    if (is_wp_error($user) && $user->get_error_code() === 'otp_required') {
        // Получаем пользователя по логину
        $user = get_user_by('login', $username);
        if (!$user) {
            return new WP_Error('invalid_user', __('Пользователь не найден.'));
        }

        if (empty($_POST['login_otp'])) {
            return new WP_Error('empty_otp', __('Пожалуйста, введите одноразовый пароль.'));
        }

        $otp_stored = get_user_meta($user->ID, 'login_otp_code', true);
        $otp_time = get_user_meta($user->ID, 'login_otp_time', true);
        $otp_input = sanitize_text_field($_POST['login_otp']);

        if (!$otp_stored || !$otp_time || (time() - $otp_time > 300)) {
            return new WP_Error('otp_expired', __('Срок действия одноразового пароля истёк. Попробуйте войти заново.'));
        }

        if ($otp_input !== $otp_stored) {
            return new WP_Error('otp_invalid', __('Неверный одноразовый пароль.'));
        }

        // Удаляем OTP после успешной проверки
        delete_user_meta($user->ID, 'login_otp_code');
        delete_user_meta($user->ID, 'login_otp_time');

        return $user; // Успешная аутентификация
    }

    return $user;
}

Проверка результата после внедрения

  • Попробуйте войти с правильным логином и паролем: вместо входа появится сообщение о необходимости ввести OTP.
  • Проверьте почту пользователя — должен прийти код из 6 цифр.
  • Введите код в дополнительное поле — вход должен пройти успешно.
  • Если код неверен или истёк, должна появиться соответствующая ошибка.
  • При повторном входе без ввода кода или с неправильным кодом доступ должен быть запрещён.

Частые ошибки и как их исправить

  • OTP не приходит на email: проверьте корректность настроек SMTP на сервере и наличие функции wp_mail(). Для отладки используйте плагин WP Mail Logging.
  • Ошибка «otp_required» не выводится: убедитесь, что фильтры authenticate подключены с правильным приоритетом (30 и 40 соответственно).
  • Одноразовый пароль принимается всегда: проверьте, что в коде реализена проверка времени жизни OTP (не более 5 минут).
  • Форма входа не отображает поле для OTP: проверьте, что хук login_form добавлен правильно и не конфликтует с темой.

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

  • Используйте HTTPS для передачи данных формы входа, чтобы защитить OTP от перехвата.
  • Ограничьте количество попыток ввода OTP, чтобы избежать перебора кода.
  • Для массовых сайтов рассмотрите интеграцию с SMS-сервисом для отправки кода вместо email.
  • Удаляйте OTP из user_meta сразу после успешного входа, чтобы исключить повторное использование.
  • При необходимости расширьте функционал для поддержки повторной отправки OTP с задержкой (например, 30 секунд между отправками).

Сравнение вариантов реализации OTP в WordPress

ВариантПлюсыМинусыПример
Плагин (например, WP 2FA)Быстро, поддержка, обновленияНагрузка, конфликт с другими плагинамиWP 2FA
Собственный код (описанный выше)Легковесно, гибко, без сторонних зависимостейТребует навыков, поддержка на васКод из статьи
Внешняя интеграция (SMS, OAuth)Максимальная безопасностьСложность, дополнительные расходыИнтеграция API
Как заблокировать вход в WordPress по стране
07.04.2026
Как отключить кеширование страницы входа в WordPress
15.02.2026
Как запретить доступ к wp-login.php для определённых ролей пользователей в WordPress
04.05.2026
Как сделать двойной вход в WordPress
04.02.2026
Как защитить WordPress от Brute Force атак с помощью Limit Login Attempts
20.01.2026

wp-login.php - это страница входа в системе управления вордпресс. Если Вы хотите изменить внешний вид страницы входа - читайте здесь. Если вам нужно защитить админку - подробный мануал. Вы можете установить плагин Clearfy, в котором есть функция защиты админки и страницы входа.