2026年5月20日
2026年5月20日
WordPressのアクティビティログを設定する方法
はじめに
アクティビティログ(監査ログ)は、WordPressサイトで行われた操作(ログイン・投稿変更・設定変更・プラグイン操作等)を記録します。不正アクセスの検出・コンプライアンス要件の充足・問題発生時の原因究明に不可欠です。
症状・原因
- 誰かが投稿を変更したが誰の操作かわからない
- 不正ログインが疑われるがアクセスログだけでは詳細が不明
- 管理者複数人でサイトを運営しており操作履歴の追跡が必要
- コンプライアンス要件でユーザー操作の記録が義務付けられている
解決手順
ステップ1:WP Activity Log プラグインを設定する
# WP Activity Log をインストール・有効化
wp plugin install wp-security-audit-log --activate
# プラグインの設定(WP-CLI経由)
wp option update wsal_pruning_date "6 months" # ログを6ヶ月保持
# アクティビティログの確認
wp eval "
if (function_exists('wsal_freemius')) {
echo 'WP Activity Log is active' . PHP_EOL;
}
"
// WP Activity Log が記録するイベント(主要なもの):
// - ユーザーのログイン・ログアウト・ログイン失敗
// - 投稿・ページの作成・編集・削除・公開
// - ユーザーアカウントの作成・変更・削除
// - プラグイン・テーマのインストール・有効化・無効化・削除
// - WordPress 設定・パーマリンク・メニューの変更
// - メディアファイルのアップロード・削除
// - コメントの承認・スパム・削除
// - ウィジェット・カスタマイザーの変更
ステップ2:カスタムアクティビティログを実装する
// functions.php: 独自のアクティビティログシステム
// ① ログテーブルを作成(プラグイン有効化時)
function create_activity_log_table(): void {
global $wpdb;
$table_name = $wpdb->prefix . 'activity_log';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_id bigint(20) unsigned NOT NULL DEFAULT 0,
action varchar(100) NOT NULL,
object_type varchar(50) NOT NULL,
object_id bigint(20) NOT NULL DEFAULT 0,
message text NOT NULL,
ip_address varchar(45) NOT NULL,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY created_at (created_at)
) $charset_collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql);
}
add_action('after_switch_theme', 'create_activity_log_table');
// ② ログを記録する共通関数
function log_activity(string $action, string $object_type, int $object_id, string $message): void {
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'activity_log',
[
'user_id' => get_current_user_id(),
'action' => sanitize_key($action),
'object_type' => sanitize_key($object_type),
'object_id' => $object_id,
'message' => sanitize_textarea_field($message),
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
'created_at' => current_time('mysql'),
],
['%d', '%s', '%s', '%d', '%s', '%s', '%s']
);
}
ステップ3:重要な操作をログに記録するフックを設定する
// functions.php: 各操作をログに記録
// ① ログイン成功・失敗を記録
add_action('wp_login', function(string $user_login, \WP_User $user): void {
log_activity('login_success', 'user', $user->ID, "ログイン成功: {$user_login}");
}, 10, 2);
add_action('wp_login_failed', function(string $username): void {
global $wpdb;
$wpdb->insert($wpdb->prefix . 'activity_log', [
'user_id' => 0,
'action' => 'login_failed',
'object_type' => 'user',
'object_id' => 0,
'message' => "ログイン失敗: {$username}",
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
'created_at' => current_time('mysql'),
], ['%d', '%s', '%s', '%d', '%s', '%s', '%s']);
});
// ② 投稿の変更を記録
add_action('post_updated', function(int $post_id, \WP_Post $after, \WP_Post $before): void {
if ($before->post_status !== $after->post_status) {
log_activity('post_status_changed', 'post', $post_id,
"投稿ステータス変更: {$before->post_status} → {$after->post_status} ({$after->post_title})");
}
if ($before->post_content !== $after->post_content) {
log_activity('post_updated', 'post', $post_id, "投稿を更新: {$after->post_title}");
}
}, 10, 3);
// ③ プラグインの有効化・無効化を記録
add_action('activated_plugin', function(string $plugin): void {
log_activity('plugin_activated', 'plugin', 0, "プラグイン有効化: {$plugin}");
});
add_action('deactivated_plugin', function(string $plugin): void {
log_activity('plugin_deactivated', 'plugin', 0, "プラグイン無効化: {$plugin}");
});
// ④ ユーザー権限変更を記録
add_action('set_user_role', function(int $user_id, string $role, array $old_roles): void {
$user = get_userdata($user_id);
$old_role = implode(', ', $old_roles);
log_activity('user_role_changed', 'user', $user_id,
"ユーザー権限変更: {$user->user_login} {$old_role} → {$role}");
}, 10, 3);
ステップ4:ログを管理画面で確認できるようにする
// functions.php: アクティビティログの管理画面ページ
add_action('admin_menu', function(): void {
add_menu_page(
'アクティビティログ', 'アクティビティログ',
'manage_options', 'activity-log',
'render_activity_log_page',
'dashicons-list-view', 80
);
});
function render_activity_log_page(): void {
global $wpdb;
$table = $wpdb->prefix . 'activity_log';
$logs = $wpdb->get_results(
"SELECT l.*, u.user_login FROM {$table} l
LEFT JOIN {$wpdb->users} u ON l.user_id = u.ID
ORDER BY l.created_at DESC LIMIT 100"
);
echo '<div class="wrap"><h1>アクティビティログ</h1>';
echo '<table class="widefat striped"><thead><tr>';
echo '<th>日時</th><th>ユーザー</th><th>操作</th><th>詳細</th><th>IP</th>';
echo '</tr></thead><tbody>';
foreach ($logs as $log) {
$user = $log->user_login ?: '未ログイン';
echo '<tr>';
echo '<td>' . esc_html($log->created_at) . '</td>';
echo '<td>' . esc_html($user) . '</td>';
echo '<td>' . esc_html($log->action) . '</td>';
echo '<td>' . esc_html($log->message) . '</td>';
echo '<td>' . esc_html($log->ip_address) . '</td>';
echo '</tr>';
}
echo '</tbody></table></div>';
}
ステップ5:不審な操作を検出してアラートを送る
// functions.php: 不審な操作を検出
add_action('activity_logged', function(string $action, int $user_id, string $ip): void {
// 深夜の管理者操作を通知
$hour = (int) current_time('G');
if (in_array($action, ['plugin_activated', 'user_role_changed', 'option_updated'], true)
&& ($hour < 5 || $hour > 23)) {
wp_mail(
get_option('admin_email'),
"[警告] 深夜の管理操作: {$action}",
"IP: {$ip}\nユーザーID: {$user_id}\n時刻: " . current_time('Y-m-d H:i:s')
);
}
}, 10, 3);
# ログをエクスポート(定期バックアップ用)
wp eval "
global \$wpdb;
\$logs = \$wpdb->get_results(\"SELECT * FROM {\$wpdb->prefix}activity_log ORDER BY created_at DESC\", ARRAY_A);
\$csv = array_map('str_getcsv', array_map('array_values', \$logs));
echo implode(PHP_EOL, array_map(fn(\$row) => implode(',', \$row), \$csv));
" > /var/backups/wordpress/activity_log_$(date +%Y%m%d).csv
注意事項
- アクティビティログはデータベースに蓄積されるためストレージを消費します。定期的に古いログを削除するか、外部ストレージに保存する仕組みを設けてください。
WP Activity Logプラグインの「Pruning」設定で自動削除期間を設定できます - ログに記録するIPアドレスはCloudflare等のプロキシを経由する場合は
HTTP_CF_CONNECTING_IPやHTTP_X_FORWARDED_FORヘッダーから取得する必要があります - ログテーブルには個人情報(IPアドレス・ユーザー名)が含まれます。プライバシーポリシーへの記載とGDPR等の規制への対応を確認してください
まとめ
アクティビティログの設定は①wp plugin install wp-security-audit-logでプラグインを導入、②独自実装の場合はactivity_logテーブルを作成して共通log_activity()関数を定義、③wp_login・post_updated・activated_plugin・set_user_roleフックで操作を記録、④管理画面ページで直近100件を一覧表示、⑤深夜の管理操作を検出してメール通知します。