Логирование действий пользователей, особенно попыток авторизации, является важной частью безопасности и отладки WordPress-сайта. В этой статье мы подробно рассмотрим, как создать собственный лог авторизации в WordPress, фиксирующий успешные входы, неудачные попытки и выходы пользователей. Также приведём практические примеры кода для реализации и советы по расширению функционала.
Зачем нужен подробный лог авторизации в WordPress
Стандартный WordPress не ведёт детального лога всех попыток входа в систему. Это создаёт проблему при расследовании взломов, выявлении подозрительной активности и мониторинге пользователей. Подробный лог позволяет:
- Отслеживать дату, время и IP-адрес попыток входа.
- Определять успешные и неудачные логины.
- Фиксировать причины неудачных попыток (неверный пароль, отсутствующий пользователь).
- Мониторить выходы из системы.
- Получать уведомления о подозрительной активности.
Реализация собственного лога позволяет гибко настраивать формат хранения и интегрировать с другими системами.
Создание таблицы для хранения логов авторизации
Для удобства и эффективности мы создадим собственную таблицу в базе данных WordPress для хранения логов. Это позволит быстро производить выборки и обеспечит масштабируемость.
Пример функции для создания таблицы (рекомендуется запускать при активации плагина или темы):
function wpexamples_create_login_log_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'wpex_login_log';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
user_login VARCHAR(60) NOT NULL,
user_id BIGINT(20) UNSIGNED NULL,
ip_address VARCHAR(100) NOT NULL,
login_status VARCHAR(20) NOT NULL,
message TEXT NULL,
login_time DATETIME NOT NULL,
PRIMARY KEY (id),
INDEX login_time_idx (login_time),
INDEX user_id_idx (user_id)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta($sql);
}
// Для примера вызовем функцию при инициализации темы
add_action('after_setup_theme', 'wpexamples_create_login_log_table');Таблица содержит ключевые поля: логин пользователя, ID, IP-адрес, статус попытки (успех, ошибка), сообщение с описанием и время события.
Логирование успешных и неуспешных попыток входа
Для отслеживания логинов используем хуки wp_login (успешный вход) и wp_authenticate_user (проверка пользователя при попытке входа).
Логирование успешного входа
Хук wp_login срабатывает после успешной авторизации. Пример записи лога:
function wpexamples_log_successful_login($user_login, $user) {
global $wpdb;
$table = $wpdb->prefix . 'wpex_login_log';
$ip = wpexamples_get_user_ip();
$wpdb->insert($table, [
'user_login' => $user_login,
'user_id' => $user->ID,
'ip_address' => $ip,
'login_status' => 'success',
'message' => 'User logged in successfully',
'login_time' => current_time('mysql')
]);
}
add_action('wp_login', 'wpexamples_log_successful_login', 10, 2);Логирование неудачных попыток входа
Для перехвата ошибок аутентификации используем фильтр wp_authenticate_user. В случае ошибки возвращается объект WP_Error, который мы обработаем для записи события.
function wpexamples_log_failed_login($user, $username, $password) {
if (is_wp_error($user)) {
global $wpdb;
$table = $wpdb->prefix . 'wpex_login_log';
$ip = wpexamples_get_user_ip();
$error_codes = implode(', ', $user->get_error_codes());
$error_messages = implode('; ', $user->get_error_messages());
$wpdb->insert($table, [
'user_login' => $username,
'user_id' => null,
'ip_address' => $ip,
'login_status' => 'failed',
'message' => "Codes: $error_codes. Messages: $error_messages",
'login_time' => current_time('mysql')
]);
}
return $user;
}
add_filter('wp_authenticate_user', 'wpexamples_log_failed_login', 20, 3);Функция определения IP-адреса пользователя
Для корректного логирования IP-адреса пользователя используем вспомогательную функцию, учитывающую прокси и заголовки:
function wpexamples_get_user_ip() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
return sanitize_text_field($_SERVER['HTTP_CLIENT_IP']);
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
return sanitize_text_field(trim($ips[0]));
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
return sanitize_text_field($_SERVER['REMOTE_ADDR']);
}
return 'UNKNOWN';
}Логирование выхода пользователя
Для полноты картины полезно фиксировать и выходы пользователей. Для этого используем хук wp_logout:
function wpexamples_log_logout() {
global $wpdb;
$user = wp_get_current_user();
if ($user->ID === 0) {
return; // Неавторизованный пользователь
}
$table = $wpdb->prefix . 'wpex_login_log';
$ip = wpexamples_get_user_ip();
$wpdb->insert($table, [
'user_login' => $user->user_login,
'user_id' => $user->ID,
'ip_address' => $ip,
'login_status' => 'logout',
'message' => 'User logged out',
'login_time' => current_time('mysql')
]);
}
add_action('wp_logout', 'wpexamples_log_logout');Просмотр и использование логов авторизации
Накопленные данные можно просматривать через кастомную страницу в админке, экспортировать или использовать для автоматических оповещений. Пример простого запроса к базе для получения последних 10 событий:
function wpexamples_get_last_login_logs($limit = 10) {
global $wpdb;
$table = $wpdb->prefix . 'wpex_login_log';
return $wpdb->get_results($wpdb->prepare("SELECT * FROM $table ORDER BY login_time DESC LIMIT %d", $limit));
}Для визуализации можно создать страницу в админке с таблицей событий и фильтрами по пользователям, IP и статусам.
Рекомендации по безопасности и производительности
При реализации логирования важно:
- Ограничивать размер таблицы, удаляя старые записи или архивируя данные.
- Очищать вводимые данные, чтобы избежать инъекций.
- Защищать доступ к логам, чтобы не раскрывать конфиденциальную информацию.
- Оптимизировать запросы и создавать индексы для быстрого поиска.
Альтернативные решения и плагины
Если не хочется писать код, можно использовать готовые плагины для логирования входов и безопасности. Среди популярных:
- Clearfy Pro — плагин с расширенными функциями логирования и оптимизации безопасности.
- WP Security Audit Log — мощный инструмент для отслеживания событий WordPress.
Однако написание собственного лога даёт максимальную гибкость и минимизирует нагрузку на систему.