WordPress 用户注册:开放、审核与防机器注册
「任何人都可以注册」这个勾一旦打开,后台用户列表一周之内就能多出几百条垃圾账号,注册邮箱清一色是临时域名。要么别开,要么开之前把下面几层防护配齐,中间状态最难受——开关开着一半,既没有验证也没有审核,等于对外开放了一个写库接口。
先决定开放还是关闭
开关只有一处:「设置 → 常规 → 会员资格 → 任何人都可以注册」。勾上之后,登录页 /wp-login.php?action=register 会出现注册表单,同时「设置 → 讨论 → 新用户默认角色」开始生效。
绝大多数企业站不需要开放注册。开放的理由只有一个:站点本身提供会员内容、论坛、投稿或商城账户。如果只是想让人留言,评论本来就不需要注册,别为了「看起来功能完整」把这个开关打开,那只会给自己增加一份长期清理的工作。
关着的时候,wp-login.php?action=register 会提示注册功能已关闭,但登录、找回密码都正常,两件事互相独立,这点后面还会细说。
还有一个折中方案值得考虑:不开公开放注册,只在活动或会员招募期间临时打开,配合审核和验证码,活动结束就关掉。这样既拿到了名单,又不用长期维护一个开放的注册入口,对绝大多数中小企业站点是性价比最高的做法。
默认角色别给高
默认角色决定新注册的人一进来能做什么。WordPress 五个角色的差别很实在:
| 角色 | 能做到什么 | 适合谁 |
|---|---|---|
| 订阅者 subscriber | 只能改自己的资料,不能进文章编辑 | 普通注册用户、会员 |
| 投稿者 contributor | 能写草稿,不能发布、不能传媒体库外的东西 | 外部投稿 |
| 作者 author | 能发布自己的文章 | 签约作者 |
| 编辑 editor | 能改所有人的文章、管分类 | 内容负责人 |
| 管理员 administrator | 全部权限,含插件、主题、用户 | 仅站点负责人 |
默认必须是订阅者。设成投稿者,等于任何人都能往后台塞草稿,你的「待审」列表会被广告塞满;设成作者,等于任何人都能直接发布内容。这两个设置在开放注册的站点上等于把内容安全交出去,而且在后台日志里很难追责。
注册后要不要审核
WordPress 没有内置审核流程,注册即生效,这点跟很多国内建站系统不一样。要实现「注册后待审」,三条路:
- 默认角色设成订阅者,人工在「用户 → 所有用户」里核对后改角色。最简单,适合每周只有几个注册的站点。
- 用插件做邮箱验证加管理员批准,注册量上到每天几十个时用这个。
- 自己写:注册时写入一个状态字段,登录时拦截。
自己写的好处是不依赖插件,坏处是维护成本在你身上。核心逻辑就两个钩子:
add_action( 'user_register', function( $uid ) {
update_user_meta( $uid, 'account_status', 'pending' );
wp_mail( get_option( 'admin_email' ), '新用户待审', '用户 ID:' . $uid );
} );
add_filter( 'wp_authenticate_user', function( $user ) {
if ( is_wp_error( $user ) ) {
return $user;
}
if ( 'pending' === get_user_meta( $user->ID, 'account_status', true ) ) {
return new WP_Error( 'pending', '账号正在审核,通过后会邮件通知。' );
}
return $user;
}, 10, 1 );
审核通过时把 account_status 改成 approved,或者直接删掉这个 meta。注意 wp_authenticate_user 只拦登录,不拦已经存在的 cookie,所以改状态后最好让该用户重新登录一次。
防机器注册的四层
机器人注册不挑站点大小,只要表单能被找到就会被试。四种手段各有代价,按需组合:
| 手段 | 能拦住什么 | 代价 |
|---|---|---|
| 图形验证码 | 脚本批量提交 | 影响无障碍,读者多一步操作 |
| 邮箱验证链接 | 一次性邮箱、假地址 | 依赖稳定发信,必须配 SMTP |
| 提交频率限制 | 短时间高频注册 | 公司共享出口 IP 容易误伤 |
| 蜜罐隐藏字段 | 自动填表的通用机器人 | 对定向攻击无效 |
企业站开「蜜罐加频率限制」基本够用;有会员体系的站点再加邮箱验证。四层全上没有必要,会把真实用户的转化率压下去。
蜜罐的实现很简单:加一个用 CSS 隐藏的输入框,正常人看不见也不会填,机器人会把所有 input 填满。
add_action( 'register_form', function() {
echo '<p class="hp-field"><input type="text" name="website_url" value=""></p>';
} );
add_filter( 'registration_errors', function( $errors ) {
if ( ! empty( $_POST['website_url'] ) ) {
$errors->add( 'bot', '注册失败,请稍后再试。' );
}
return $errors;
} );
配套在样式表里写 .hp-field{display:none}。别用 visibility:hidden 或者把它挪到屏幕外太远处,部分机器人会跳过不可见元素,display:none 的命中率反而更高。
频率限制用 transient 按 IP 记数就够,不用上 Redis:
add_filter( 'registration_errors', function( $errors ) {
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
$key = 'reg_' . md5( $ip );
$n = (int) get_transient( $key );
if ( $n >= 3 ) {
$errors->add( 'too_fast', '注册过于频繁,请一小时后再试。' );
}
set_transient( $key, $n + 1, HOUR_IN_SECONDS );
return $errors;
} );
阈值别设成 1。一个办公室十几个人共用一个出口 IP,设太严会把真实客户挡在门外,客服电话比垃圾账号更麻烦。
邮箱验证这一步有个前提经常被忽略:PHP 的 mail() 在国内服务器上基本发不出去,25 端口被封,云厂商也默认禁用。所以「验证邮件」功能上线前必须先把 SMTP 配通,否则用户点完注册什么也收不到,第二天就来问「为什么我注册没反应」。装一个 SMTP 插件,用企业邮箱账号发信,端口走 465 或 587,配完先给自己发一封测试邮件确认能进收件箱而不是垃圾箱。
注册页怎么自定义
默认注册页由 wp-login.php 生成,样式跟站点完全不搭,字段也只有用户名和邮箱。三种改法:
- 样式覆盖:用 login_enqueue_scripts 挂自己的 CSS,改 logo、配色、按钮,登录和注册页一起生效,改动最小。
- 换成独立页面:建一个普通页面放自定义表单,提交到 admin-post.php,服务端用 wp_create_user 建号。
- 用插件:Members、Ultimate Member 这类直接提供前台注册页、字段管理和审核流。
自己写表单要注意三件事:nonce 校验、用户名过滤(sanitize_user)、邮箱是否已存在。wp_create_user 失败时返回的是 WP_Error,不能直接当 ID 用:
$uid = wp_create_user( $user, $pass, $email );
if ( is_wp_error( $uid ) ) {
// 可能是 username_exists、email_exists、illegal_user_login
echo esc_html( $uid->get_error_message() );
}
还要处理一个常见需求:注册时让用户填公司、电话。这些字段用 add_user_meta 存,别直接往 wp_users 里加列,升级时会被覆盖。表单提交前做一次 sanitize_text_field,输出时 esc_html,两步都不能省。
关掉注册之后
取消勾选「任何人都可以注册」只影响新注册,已有用户照常登录,密码、角色、已发文章都不受影响。这是很多人担心的点,其实开关的作用范围很窄,就是注册表单本身。
但有个例外:如果你之前用插件做了前台注册页,关掉这个开关后插件可能仍然能建号,因为它走的是 wp_create_user,不看这个 option。要彻底关,得在插件设置里一起关,或者在 user_register 钩子上直接退出。
add_action( 'user_register', function( $uid ) {
if ( ! get_option( 'users_can_register' ) && ! current_user_can( 'create_users' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
wp_delete_user( $uid );
wp_die( '本站已关闭注册。' );
}
} );
已经进来的垃圾账号怎么清:在「用户 → 所有用户」按注册时间排序,批量删除,删除时勾选「删除该用户的文章」,投稿者的草稿会一并清掉。删之前先导出邮箱列表存档,避免把真实客户误删。用户列表的筛选和批量操作在 后台入门 里有截图级的说明。
整套做下来,注册这件事的核心就两句:默认最小权限,至少一层人机校验。它属于 安全加固 的一部分,和登录保护、防火墙规则一起规划效果最好——机器人连登录页都摸不到的时候,注册攻击自然少一大半。如果站点还要接短信、企业微信或者商城账户体系,注册流程会更复杂,改造思路可以参考 插件定制,涉及验证码和发信的服务选型可以直接打 13280692153 问,或者走 联系我们。