Как создать кастомный плагин для журналов входов в WordPress

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

Почему нужен кастомный плагин для журналов входов

Стандартный WordPress не ведёт полноценный лог входов пользователей. Хотя существуют популярные плагины, например, Clearfy Pro с расширенными возможностями безопасности, иногда требуется лёгкое и гибкое решение под конкретные задачи без избыточного функционала.

Создание своего плагина позволит:

  • Записывать только нужные события;
  • Добавлять кастомные поля и метаданные;
  • Интегрировать запись в существующий функционал сайта;
  • Оптимизировать производительность и не загромождать базу данных.

Основные задачи плагина для журналов входов

Плагин должен выполнять следующие функции:

  • Логировать успешные входы пользователей с указанием ID, IP, времени;
  • Логировать неудачные попытки входа с причиной отказа;
  • Предоставлять администратору простой интерфейс для просмотра журнала;
  • Обеспечивать возможность фильтрации и экспорта данных.

Рассмотрим этапы создания такого плагина и приведём примеры кода.

Создание плагина: структура и регистрация хуков

Начнём с создания папки в wp-content/plugins/wpauth-login-log и файла wpauth-login-log.php с базовым описанием плагина:

<?php
/*
Plugin Name: WPAUTH Login Log
Description: Журнал попыток входа пользователей
Version: 1.0
Author: WPAUTH Team
*/

// Защита от прямого доступа
if (!defined('ABSPATH')) exit;

Далее подключим хуки для логирования успешных и неудачных входов:

add_action('wp_login', 'wpauth_login_log_success', 10, 2);
add_action('wp_login_failed', 'wpauth_login_log_failed');

function wpauth_login_log_success($user_login, $user) {
    global $wpdb;
    $table = $wpdb->prefix . 'wpauth_login_log';
    $wpdb->insert($table, [
        'user_id' => $user->ID,
        'login' => $user_login,
        'ip_address' => wpauth_get_user_ip(),
        'status' => 'success',
        'date' => current_time('mysql')
    ]);
}

function wpauth_login_log_failed($user_login) {
    global $wpdb;
    $table = $wpdb->prefix . 'wpauth_login_log';
    $wpdb->insert($table, [
        'user_id' => 0,
        'login' => $user_login,
        'ip_address' => wpauth_get_user_ip(),
        'status' => 'failed',
        'date' => current_time('mysql')
    ]);
}

function wpauth_get_user_ip() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

Создание таблицы для хранения логов

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

register_activation_hook(__FILE__, 'wpauth_create_login_log_table');

function wpauth_create_login_log_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpauth_login_log';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table_name (
      id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      user_id bigint(20) unsigned NOT NULL,
      login varchar(60) NOT NULL,
      ip_address varchar(100) NOT NULL,
      status varchar(10) NOT NULL,
      date datetime NOT NULL,
      PRIMARY KEY (id),
      KEY user_id (user_id),
      KEY status (status),
      KEY date (date)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}

Создание административного интерфейса

Чтобы удобно просматривать логи, добавим страницу в админ-панель. Для этого используем хук admin_menu:

add_action('admin_menu', 'wpauth_login_log_admin_menu');

function wpauth_login_log_admin_menu() {
    add_menu_page(
        'Журнал входов',
        'Журнал входов',
        'manage_options',
        'wpauth-login-log',
        'wpauth_login_log_admin_page',
        'dashicons-list-view',
        80
    );
}

function wpauth_login_log_admin_page() {
    global $wpdb;
    $table = $wpdb->prefix . 'wpauth_login_log';

    // Параметры фильтрации
    $status_filter = isset($_GET['status']) ? sanitize_text_field($_GET['status']) : '';
    $query = "SELECT * FROM $table";
    $where = [];
    if ($status_filter === 'success' || $status_filter === 'failed') {
        $where[] = $wpdb->prepare("status = %s", $status_filter);
    }
    if (!empty($where)) {
        $query .= ' WHERE ' . implode(' AND ', $where);
    }
    $query .= ' ORDER BY date DESC LIMIT 100';

    $logs = $wpdb->get_results($query);

    echo '<h1>Журнал входов пользователей</h1>';
    echo '<form method="get">';
    echo '<input type="hidden" name="page" value="wpauth-login-log" />';
    echo '<label>Фильтр по статусу: </label>';
    echo '<select name="status" onchange="this.form.submit()">';
    echo '<option value="">Все</option>';
    echo '<option value="success"' . selected($status_filter, 'success', false) . '>Успешные</option>';
    echo '<option value="failed"' . selected($status_filter, 'failed', false) . '>Неудачные</option>';
    echo '</select>';
    echo '</form>';

    echo '<table class="wp-list-table widefat fixed striped">';
    echo '<thead><tr><th>ID</th><th>Пользователь</th><th>Логин</th><th>IP адрес</th><th>Статус</th><th>Дата</th></tr></thead>';
    echo '<tbody>';
    if ($logs) {
        foreach ($logs as $log) {
            $user_display = $log->user_id ? get_userdata($log->user_id)->user_login : 'Гость';
            echo "<tr>";
            echo "<td>{$log->id}</td>";
            echo "<td>" . esc_html($user_display) . "</td>";
            echo "<td>" . esc_html($log->login) . "</td>";
            echo "<td>" . esc_html($log->ip_address) . "</td>";
            echo "<td>" . esc_html($log->status) . "</td>";
            echo "<td>" . esc_html($log->date) . "</td>";
            echo "</tr>";
        }
    } else {
        echo "<tr><td colspan='6'>Записей не найдено</td></tr>";
    }
    echo '</tbody></table>';
}

Расширение функционала: уведомления и экспорт

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

Также полезна функция экспорта логов в CSV для последующего анализа. Это можно сделать, добавив кнопку экспорта и обработчик, который формирует CSV-файл с выбранными записями.

Для примера реализации экспорта можно использовать следующий код:

add_action('admin_post_wpauth_export_logs', 'wpauth_export_logs_csv');

function wpauth_export_logs_csv() {
    if (!current_user_can('manage_options')) {
        wp_die('Доступ запрещён');
    }
    global $wpdb;
    $table = $wpdb->prefix . 'wpauth_login_log';
    $logs = $wpdb->get_results("SELECT * FROM $table ORDER BY date DESC");

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename=wpauth_login_logs.csv');

    $output = fopen('php://output', 'w');
    fputcsv($output, ['ID', 'User ID', 'Login', 'IP Address', 'Status', 'Date']);

    foreach ($logs as $log) {
        fputcsv($output, [(int)$log->id, (int)$log->user_id, $log->login, $log->ip_address, $log->status, $log->date]);
    }
    fclose($output);
    exit;
}

Добавьте кнопку на страницу администратора с формой:

<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
    <input type="hidden" name="action" value="wpauth_export_logs" />
    <button type="submit" class="button button-primary">Экспортировать логи в CSV</button>
</form>

Оптимизация и безопасность

При работе с журналами важно учитывать производительность сайта. Рекомендуется очищать старые записи периодически, например, с помощью WP-Cron:

add_action('wpauth_cleanup_old_logs', 'wpauth_delete_old_logs');

function wpauth_delete_old_logs() {
    global $wpdb;
    $table = $wpdb->prefix . 'wpauth_login_log';
    $wpdb->query($wpdb->prepare("DELETE FROM $table WHERE date < %s", date('Y-m-d H:i:s', strtotime('-90 days'))));
}

if (!wp_next_scheduled('wpauth_cleanup_old_logs')) {
    wp_schedule_event(time(), 'daily', 'wpauth_cleanup_old_logs');
}

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

Заключение

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

Если хотите более продвинутые функции, обратите внимание на плагины из каталога WPShop, например Clearfy Pro, который содержит готовые решения для безопасности и мониторинга.

WordPress автоматическая блокировка подозрительных входов: настройка и примеры кода
17.12.2025
WordPress авторизация через REST API: практическое руководство с примерами кода
25.12.2025
WordPress удаление пользователя при удалённом запросе: практическое руководство
06.12.2025
WooCommerce: авторизация по телефонному номеру без SMS-провайдера
16.05.2026
WooCommerce: ограничение доступа к продуктам по ролям пользователей
07.05.2026