WordPress登录页集成字母验证码需通过PHP脚本动态生成图片流(PNG/JPEG),由<img>标签引用;必须用login_form钩子注入表单字段,wp_authenticate_user钩子校验session中存储的剔除易混字符(如O/0、I/1)的验证码,且脚本须UTF-8无BOM、仅输出图像、禁用额外输出。

直接集成字母验证码到 WordPress,不能靠“在 HTML 里加 PHP 标签”实现——PHP 脚本必须由服务器执行并输出图片流,前端用 <img> 引用该脚本 URL 才能显示。关键在于后端生成逻辑 + 前端表单联动 + session 校验闭环。
captcha.php 必须输出 PNG/JPEG,且不能有额外输出
常见错误是:脚本开头或结尾有多余空格、echo、print 或 BOM 字符,导致 header('Content-Type: image/png') 失败,浏览器显示“损坏的图像”或空白。GD 库输出前必须确保:
- 文件保存为 UTF-8 无 BOM 格式(VS Code 右下角可切换)
- 脚本顶部只有
session_start();,后面紧跟图像生成逻辑 - 调用
imagepng()后立即exit;或die;,防止后续 PHP 输出干扰二进制流 - 确认 GD 扩展已启用:
extension_loaded('gd')返回true
WordPress 登录页注入字母验证码需 hook login_form
不能直接改 wp-login.php,要用 login_form 钩子插入 HTML。示例代码片段(放入插件主文件):
add_action('login_form', 'inject_captcha_field');
function inject_captcha_field() {
$captcha_url = plugins_url('captcha.php', __FILE__);
echo '<p class="captcha-field">';
echo '<label for="captcha_input">验证码(字母+数字)</label>';
echo '<input type="text" name="captcha_input" id="captcha_input" autocomplete="off" required>';
echo '<img src="' . esc_url($captcha_url) . '" alt="验证码" onclick="this.src=\'' . esc_url($captcha_url) . '?t=\' + Math.random();" style="cursor:pointer;">';
echo '</p>';
}
注意:onclick 中加随机参数是为了强制刷新,避免浏览器缓存旧图;esc_url() 是必须的安全过滤,否则可能被 XSS 注入。
安全的随机密码生成器。支持自定义长度、字符类型(大写/小写字母、数字、特殊符号),排除相似字符,批量生成。纯 Python 标准库,无需 API 密钥。
立即学习“PHP免费学习笔记(深入)”;
校验逻辑必须在 wp_authenticate_user 中拦截
用户提交登录表单后,WordPress 在认证前会触发 wp_authenticate_user 过滤器。这里读取 $_POST['captcha_input'] 并比对 $_SESSION['captcha_code']:
- 必须先调用
session_start()(可在插件激活时或钩子回调里判断是否已启动) - 比对后建议立刻
unset($_SESSION['captcha_code']),防止重放 - 若不匹配,返回
WP_Error对象,WordPress 会自动显示错误提示 - 不要依赖
$_SESSION存在就认为验证通过——要检查键是否存在、是否为空、是否过期(可加时间戳字段)
字母混淆风险:避免 O/0、I/1、l/1 等易混字符
原始示例中用 '23456789ABCDEFGHJKLMNPQRSTUVWXYZ' 已剔除易混字符,这是关键细节。如果自己拼接字符集,务必手动排除:
-
O和0(零) -
I、l(小写 L)和1(一) -
Z和2(在某些字体中相似)
更稳妥的做法是固定使用已验证过的字符集,比如 str_split('CEGHJKMPQRTVWXY2346789'),再 shuffle 后取 4 位。GD 绘图时也建议禁用默认字体,改用 imagettftext() 加载明确支持 ASCII 的 TTF 文件(如 DejaVuSans),否则某些字母可能无法渲染或位置偏移。


















