许多 WordPress 站长都曾遭遇恶意注册用户的困扰。例如,曾有站点被恶意注册超过 70 万用户,导致数据库短时间内膨胀了 1GB 以上,严重影响网站性能和安全。
为了解决这个问题,我们可以通过 WordPress 的定时任务功能,自动清理那些从未登录过的恶意注册用户。本文将提供一个完整、安全的实现方案。
实现原理
本方案的核心是创建一个自定义的 WordPress 定时任务(Cron Job)。该任务会定期执行,查询并删除那些符合特定条件的用户(例如,注册后从未登录过的用户)。
完整实现代码
将以下代码添加到您当前主题的 functions.php 文件末尾,或通过代码片段插件(如 Code Snippets)添加。
/**
* 1. 添加自定义的 Cron 时间间隔(例如:每10分钟)
*/
add_filter( 'cron_schedules', 'wp_cleanup_add_cron_interval' );
function wp_cleanup_add_cron_interval( $schedules ) {
$schedules['every_ten_minutes'] = array(
'interval' => 600, // 600秒 = 10分钟
'display' => __( '每隔10分钟', 'your-text-domain' )
);
return $schedules;
}
/**
* 2. 调度定时任务(如果尚未调度)
*/
if ( ! wp_next_scheduled( 'wp_cleanup_inactive_users_hook' ) ) {
wp_schedule_event( time(), 'every_ten_minutes', 'wp_cleanup_inactive_users_hook' );
}
/**
* 3. 定义定时任务要执行的操作:清理用户
*/
add_action( 'wp_cleanup_inactive_users_hook', 'wp_cleanup_inactive_users' );
function wp_cleanup_inactive_users() {
// 获取所有用户
$all_users = get_users( array( 'fields' => array( 'ID', 'user_registered' ) ) );
foreach ( $all_users as $user ) {
$user_id = $user->ID;
// 关键判断:检查用户是否从未登录过。
// 方法:检查用户元数据 `last_login` 是否存在或为空。
// 注意:WordPress 默认不记录最后登录时间,需要插件或额外代码支持。
// 这里提供一个更通用的替代方案:检查用户注册时间与当前时间差,并确保用户角色为“订阅者”等低级角色。
$user_data = get_userdata( $user_id );
$user_roles = $user_data->roles;
// 示例条件:删除注册超过7天且从未发表过文章、评论的“订阅者”角色用户
// 这是一个更安全的策略,避免误删活跃用户。
$days_old = 7;
$registered_time = strtotime( $user->user_registered );
$cutoff_time = strtotime( "-$days_old days" );
// 检查用户是否有文章或评论
$post_count = count_user_posts( $user_id );
$comment_count = get_comments( array( 'user_id' => $user_id, 'count' => true ) );
if ( in_array( 'subscriber', $user_roles ) && // 角色为订阅者
$registered_time < $cutoff_time && // 注册超过设定天数
$post_count == 0 && // 从未发表文章
$comment_count == 0 // 从未发表评论
) {
// 执行删除
// 注意:如果用户有文章,需要指定文章继承者,否则文章会被删除。
// 由于我们已确保 $post_count == 0,这里可以直接删除。
require_once( ABSPATH . 'wp-admin/includes/user.php' );
wp_delete_user( $user_id );
}
}
}
/**
* 4. (可选) 插件停用时清理定时任务
*/
register_deactivation_hook( __FILE__, 'wp_cleanup_deactivation' );
function wp_cleanup_deactivation() {
$timestamp = wp_next_scheduled( 'wp_cleanup_inactive_users_hook' );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, 'wp_cleanup_inactive_users_hook' );
}
}
代码说明与安全建议
1. 自定义时间间隔
通过 cron_schedules 过滤器添加了一个名为 every_ten_minutes 的间隔(10分钟)。您可以根据需要修改 interval 的值(单位:秒),例如改为每小时(3600秒)或每天(86400秒)。
2. 核心清理逻辑(重要)
原示例代码通过一个自定义字段(jh)判断用户,这并不通用。上述重写后的代码采用了更稳健的策略:
- 目标用户:角色为“订阅者”(Subscriber)。
- 注册时间:超过设定的天数(示例为7天)。
- 活跃度检查:确保该用户从未发表过文章或评论。
这三个条件叠加,可以极大程度地避免误删正常用户,精准打击“注册后即沉寂”的恶意用户。
3. 关于用户删除
wp_delete_user() 函数在删除拥有文章的用户时,必须指定一个文章继承者($reassign 参数),否则该用户的所有文章将被一并删除。在我们的逻辑中,由于已确保用户无文章($post_count == 0),所以可以安全地直接删除。
4. 管理定时任务
- 查看任务:可以安装 “WP Crontrol” 或 “Advanced Cron Manager” 等插件来查看和管理您的自定义定时任务。
- 停止清理:如果您想停止自动清理,只需从
functions.php中移除上述代码,或通过代码片段插件停用该片段即可。代码中已包含停用钩子作为示例。
扩展:记录用户最后登录时间
要实现更精确的“从未登录”判断,需要记录用户的最后登录时间。您可以在主题的 functions.php 中添加以下代码:
// 记录用户登录时间
add_action( 'wp_login', 'wp_record_user_last_login', 10, 2 );
function wp_record_user_last_login( $user_login, $user ) {
update_user_meta( $user->ID, 'last_login', current_time( 'mysql' ) );
}
添加此代码后,您可以将主清理函数中的判断条件改为检查 last_login 元数据是否存在。如果不存在,则说明该用户自您添加此代码后从未登录过。
通过以上方案,您可以有效自动化 WordPress 站点的用户清理工作,保持数据库的整洁与高效运行。