超级验证码安全防护
详情介绍
超级验证码插件(SuperCaptcha)使用文档
版本:1.1.0 | 作者:kuakeba.cn | 适用于 Zsens Admin 3.0+(PHP 8.2+)
一、插件简介
超级验证码为社区前台提供一套统一的验证码接管方案,内置七种主流验证方式,并支持随机切换:
- 滑块拼图(
slider) - 自由拖拽(
drag) - 旋转校正(
rotate) - 点选文字(
click) - 点选图形(
icon) - 字符识别(
word) - 数学算式(
math) - 随机切换(
random,每次请求从上述七种中随机抽取)
插件自动识别页面中的 .js-captcha 控件并替换为所选验证方式,无需修改社区模板或主题文件。可接管登录、注册、找回密码、发帖、回帖等场景,也可与原「验证码」插件共存。
二、功能特性
| 特性 | 说明 |
|---|---|
| 七种验证方式 | 覆盖滑动、拖拽、旋转、点选、识图、算术等主流交互 |
| 随机切换 | 每次刷新随机抽取一种方式,显著提高自动化破解成本 |
| 场景独立开关 | 登录/注册/找回、发帖、回帖三类场景可分别启用 |
| 服务端判题 | 答案只保存在服务端缓存,前端仅持一次性令牌,页面源码中读不到答案 |
| 一次性消费 | 每个挑战验证成功后立即失效,防止重放 |
| 错误次数限制 | 同一挑战最多允许 5 次错误,超出后强制刷新 |
| 有效期控制 | 默认 300 秒,可在 60–1800 秒之间调整 |
| 参数可调 | 拼图容差、点选数量、点选半径、旋转容差、字符长度、主题色均可配置 |
| 自动降级 | 服务器缺少 GD 扩展或单模式渲染失败时,自动降级为数学算式 |
| 模板零侵入 | 兼容社区 PJAX 软跳转与动态插入表单,自动升级新出现的验证码控件 |
| 移动端适配 | 统一使用 Pointer Events,支持鼠标、触摸与触控笔 |
三、环境要求
| 项目 | 要求 |
|---|---|
| Zsens Admin | 3.0+ |
| PHP | 8.1+(推荐 8.2+,与系统要求保持一致) |
| GD 扩展 | 必需,涉及 imagecreatetruecolor、imagepng、imagecolorallocate;未开启时所有图形验证自动降级为数学算式 |
| 社区插件 | 必须安装并启用(community),本插件依附其登录/发帖/回帖流程 |
| 缓存驱动 | 使用系统默认 Cache;请确保缓存服务正常,否则挑战无法保存 |
| 字体(可选) | 点选中文依赖 TTF/OTF 字体,缺省时自动使用字母数字 |
四、安装与升级
4.1 安装
- 将
SuperCaptcha目录整体放入项目plugins/下 - 进入后台 应用中心,找到「超级验证码」,点击 安装
- 安装时自动将
plugins/SuperCaptcha/static/复制到public/static/SuperCaptcha/ - 进入 应用中心 → 超级验证码 → 配置,选择验证方式并按需调整参数
- 打开社区前台登录、注册、发帖或回帖页面,确认验证码已替换
4.2 升级
- 覆盖
plugins/SuperCaptcha/下的全部文件 - 回到后台应用中心,对本插件执行一次 安装/更新,以刷新
public/static/SuperCaptcha/下的 JS/CSS - 前台强制刷新(Ctrl+F5)一次
静态资源 URL 自带 ?v=1.1.0 版本参数,正常升级后浏览器会自动拉取新文件;若仍显示旧样式,可手动删除 public/static/SuperCaptcha/ 后重新安装。
4.3 启用顺序建议
- 先确认社区插件运行正常
- 安装并配置超级验证码
- 在后台开关中按场景逐步启用(建议先只开登录/注册,观察无误后再开发帖与回帖)
五、后台配置
后台路径:应用中心 → 超级验证码 → 配置
| 配置项 | 键名 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|
| 启用超级验证码 | enabled | 开启 | 开/关 | 总开关。关闭后前台不再注入资源,自动回退原验证码插件 |
| 验证方式 | mode | slider | 见下方 | 八选一:七种方式 + 随机切换 |
| 登录/注册/找回 | userauthenabled | 开启 | 开/关 | 登录、注册、找回密码及对应短信发送需完成验证 |
| 发帖验证 | userpostenabled | 开启 | 开/关 | 发布/编辑主题需完成验证 |
| 回帖验证 | userreplyenabled | 开启 | 开/关 | 回复主题需完成验证 |
| 拼图容差 | tolerance | 12 | 2–50 像素 | 滑块拼图与自由拖拽允许的坐标误差 |
| 点选数量 | click_count | 4 | 2–6 个 | 每次需依次点击的字符/图形数量 |
| 点选判定半径 | click_radius | 30 | 12–60 像素 | 点击位置与目标中心的允许距离 |
| 旋转容差 | rotate_tolerance | 8 | 3–20 度 | 旋转校正允许的角度误差 |
| 字符识别长度 | word_length | 5 | 4–6 个 | 字符识别图包含的字符数 |
| 验证有效期 | expires | 300 | 60–1800 秒 | 挑战从生成到失效的时间 |
| 主题色 | theme_color | #2563eb | 十六进制 | 滑块轨道、按钮、点选标记等强调色 |
mode 可选值:
| 值 | 名称 |
|---|---|
slider | 滑块拼图 |
drag | 自由拖拽 |
rotate | 旋转校正 |
click | 点选文字 |
icon | 点选图形 |
word | 字符识别 |
math | 数学算式 |
random | 随机切换 |
配置值在服务端会再次做范围收敛,即使误填超范围数值也不会导致异常。
六、验证方式说明
6.1 滑块拼图(slider)
- 用户操作:拖动下方滑块,使拼图块与背景缺口对齐,松开后自动提交
- 判定规则:服务端比较提交的水平坐标与缺口位置,误差不超过「拼图容差」即通过
- 提交内容:
{"x":123} - 调优建议:容差越小越难;移动端用户若反馈难以对齐,可适当放宽到 15–20
6.2 自由拖拽(drag)
- 用户操作:直接按住拼图块,拖到背景缺口位置后松开
- 判定规则:横向与纵向坐标同时落在「拼图容差」范围内才通过
- 提交内容:
{"x":123,"y":45} - 调优建议:难度高于滑块拼图,适合对安全性要求更高的站点;容差建议不低于 16
6.3 旋转校正(rotate)
- 用户操作:拖动滑块,把倾斜的字符图片旋转至水平,松开后自动提交
- 判定规则:服务端比较提交角度与真实倾斜角度,误差不超过「旋转容差」即通过
- 提交内容:
{"angle":30} - 说明:图片随机倾斜 ±20°~65°,滑块范围为 -75°~75°;图片已做调色板压缩(约 9KB),加载较快
6.4 点选文字(click)
- 用户操作:按提示顺序依次点击图中的指定汉字
- 判定规则:按顺序逐点比对坐标,每个点需落在「点选判定半径」内
- 提交内容:
{"points":[[x,y],[x,y],...]} - 说明:未找到中文字体时自动改用字母数字;点数由「点选数量」控制
6.5 点选图形(icon)
- 用户操作:按提示顺序依次点击图中的指定图形(圆形、方形、三角形、菱形、星形、十字)
- 判定规则:与点选文字共用坐标判定逻辑,无需中文字体
- 提交内容:
{"points":[[x,y],...]} - 适用场景:服务器没有中文字体,或希望验证码更偏图形化时
6.6 字符识别(word)
- 用户操作:在输入框中输入图中字符,随表单一起提交
- 判定规则:服务端忽略大小写比对
- 提交内容:纯文本
- 说明:字符集剔除了易混淆的
I/O/0/1;图片含干扰线与噪点,长度由「字符识别长度」控制
6.7 数学算式(math)
- 用户操作:填写算式结果,随表单一起提交
- 判定规则:服务端按数值比对
- 提交内容:纯文本
- 说明:支持加、减、乘法;也是所有图形方式的兜底方案
6.8 随机切换(random)
- 用户操作:与当前随机到的验证方式一致
- 工作机制:每次请求挑战时,服务端从七种方式中随机抽取一种,并把真实模式写入缓存;前端只根据返回的
mode渲染,无需额外配置 - 建议:日常运营推荐使用该模式,兼顾体验与安全性
七、前台生效场景与交互
7.1 生效场景
| 场景 | 覆盖操作 | 对应开关 |
|---|---|---|
| 账号验证 | 登录、注册、找回密码、发送短信验证码 | 登录/注册/找回 |
| 发帖 | 发布主题、编辑主题 | 发帖验证 |
| 回帖 | 回复主题 | 回帖验证 |
7.2 交互流程
- 页面加载时,脚本扫描
img.js-captcha,找到所属表单及captcha、captcha_token字段 - 隐藏原验证码图片,请求
/supercaptcha/challenge获取挑战 - 按返回的
mode渲染对应控件:
- slider / drag / rotate / click / icon:操作完成后调用 /supercaptcha/verify 即时校验,通过后显示对勾
- word / math:用户输入内容,随表单提交时由服务端校验
- 表单最终提交仍使用社区的
captcha+captcha_token字段,服务端消费挑战
7.3 失败与刷新
- 验证失败:提示「验证失败,请重试」,挑战保留,可继续尝试
- 连续错误 5 次:挑战作废,提示「错误次数过多,请刷新后重试」
- 超过有效期:提示「验证已过期,请刷新后重试」
- 点击验证码旁的刷新按钮,或重新打开表单,即可获取新挑战
7.4 PJAX 与动态表单
脚本监听 pjax:end、community:pjax 以及 DOM 变化,软跳转或异步插入的新表单会自动完成验证码升级,无需手动初始化。
7.5 与原验证码插件共存
- 超级验证码启用时优先接管,原「验证码」插件自动让位
- 关闭超级验证码总开关后,社区自动回退到原验证码插件
- 若三个场景开关全部关闭,前台不显示任何验证码(与社区原有逻辑一致)
八、安全机制
| 机制 | 说明 |
|---|---|
| 答案服务端保存 | 答案与目标坐标写入 Cache,缓存键为 supercaptcha: + sha256(token) |
| 令牌随机 | 采用 randombytes(16) 生成 32 位十六进制令牌,仅允许 64 位以内的字母数字与 .- |
| 一次性消费 | 表单校验通过后立即删除挑战,无法重复使用 |
| 错误限制 | 单挑战最多 5 次错误,超过即作废 |
| 有效期 | 默认 300 秒,超时自动清理 |
| 防缓存 | 接口响应携带 no-store、no-cache 头,避免代理或浏览器缓存挑战 |
| 随机化 | 随机模式每次更换验证方式,增加自动化脚本适配成本 |
验证码只能提高自动化攻击成本,无法替代频率限制、IP 风控与行为审计。建议同时开启社区的登录/发帖频率限制。
九、常见问题
Q1:前台没有出现新的验证码?
按顺序排查:
- 后台确认插件已安装且总开关开启
- 确认对应场景开关(登录/注册/找回、发帖、回帖)已开启
- 确认社区插件已安装并启用
- 检查
public/static/SuperCaptcha/supercaptcha.js是否存在;不存在则重新安装插件 - 浏览器控制台查看是否有 404 或 JS 报错
Q2:一直提示「验证已过期,请刷新后重试」?
- 检查系统缓存是否正常(文件缓存需
runtime/可写,Redis 需连接正常) - 检查服务器时间是否准确
- 若有效期设置过短(如 60 秒),可适当调大
Q3:点选文字里显示的是字母数字,不是汉字?
服务器未找到可用中文字体。可任选一种方式解决:
- 将中文字体(如
simhei.ttf)放入plugins/SuperCaptcha/static/fonts/ - 在服务器安装常用中文字体(Windows 的
simhei.ttf、Linux 的文泉驿/Noto CJK) - 改用「点选图形」模式,不依赖中文字体
Q4:服务器没有 GD 扩展怎么办?
插件会自动降级为数学算式,功能不受影响。若希望使用图形验证,请在 PHP 中启用 GD 扩展后重启服务。
Q5:修改了 JS/CSS 但前台没变化?
静态资源在安装时复制到 public/static/SuperCaptcha/,直接改插件目录不会自动同步。执行一次插件安装/更新,或手动复制文件后强制刷新浏览器。
Q6:验证码图片加载慢?
- 旋转图已压缩到约 9KB,滑块与点选图通常在几十 KB
- 若服务器性能较弱,可改用「数学算式」或「字符识别」
- 确认未开启过于激进的图片压缩或 CDN 回源策略
Q7:移动端拖拽不跟手或页面跟着滚动?
插件已对拖拽区域设置 touch-action: none。若主题额外绑定了触摸事件,可检查是否阻止了默认行为;必要时切换为「滑块拼图」或「点选」类方式。
Q8:后台修改配置后不生效?
配置保存后即时生效,但已打开的页面仍使用旧挑战。刷新页面即可;若使用 CDN/OPcache,请清理对应缓存。
Q9:关闭插件后表单提交提示验证码错误?
关闭总开关会回退到原验证码插件。若原插件未安装或未启用,而社区仍要求验证码,请安装原「验证码」插件,或重新开启超级验证码。
十、接口说明
| 方法 | 地址 | 说明 |
|---|---|---|
| GET | /supercaptcha/challenge?token=xxx | 获取挑战;token 可省略,省略时由服务端生成 |
| POST | /supercaptcha/verify | 即时校验,参数 captcha、captcha_token |
10.1 挑战响应示例
{
"code": 1,
"msg": "ok",
"data": {
"mode": "slider",
"token": "8f14e45fceea167a5a36dedd4bea2543",
"expires": 300,
"theme": "#2563eb",
"bg": "data:image/png;base64,...",
"piece": "data:image/png;base64,...",
"width": 320,
"height": 160,
"piece_size": 48,
"piece_y": 56,
"prompt": "拖动滑块,将拼图对齐缺口"
}
}不同模式返回的字段不同:
| 模式 | 特有字段 |
|---|---|
slider | piece、piecesize、piecey |
drag | piece、piece_size |
rotate | min、max |
click / icon | count,提示文本位于 prompt |
word | length,prompt 为输入提示 |
math | 无图片字段,prompt 即算式 |
服务端返回数据中不包含 answer 与 targets,答案仅保存在缓存中。
10.2 校验响应示例
{
"code": 0,
"msg": "验证失败,请重试",
"data": { "refresh": false }
}code=1 表示通过;data.refresh=true 表示挑战已作废,需要重新获取。
10.3 各模式提交格式
| 模式 | captcha 内容 |
|---|---|
slider | {"x":123} |
drag | {"x":123,"y":45} |
rotate | {"angle":30} |
click / icon | {"points":[[x,y],[x,y]]} |
word / math | 纯文本 |
二次开发时,只需在自有表单中加入隐藏字段 captcha 与 captcha_token,并在服务端调用 SuperCaptchaService::checkUser($input, $token) 即可复用本插件。
十一、卸载与回退
- 后台关闭「启用超级验证码」总开关,可立即回退原验证码插件
- 在应用中心卸载插件后,建议手动删除
public/static/SuperCaptcha/目录 - 卸载不会影响社区数据;已生成的挑战会在有效期结束后自动失效
十二、目录结构
plugins/SuperCaptcha/
├── controller/
│ └── Front.php 前台接口(challenge / verify)
├── service/
│ └── SuperCaptchaService.php 挑战生成、校验、绘图
├── static/
│ ├── supercaptcha.css 前台样式
│ ├── supercaptcha.js 前台自动装配与交互
│ └── fonts/ 可选字体目录(自建)
├── SuperCaptchaPlugin.php 插件入口、配置、资源注入
├── plugin.json 插件元数据
├── routes.php 路由注册
├── icon.svg 插件图标
└── README.md 使用文档十三、更新日志
1.1.0
- 新增自由拖拽、旋转校正、点选文字、点选图形、字符识别、随机切换
- 新增旋转容差、字符长度配置
- 旋转图体积优化(约 56KB → 约 9KB)
- 完善 GD 缺失、字体缺失、渲染失败时的自动降级
1.0.0
- 首个版本:滑块拼图、点选、数学算式
- 支持登录/注册/找回、发帖、回帖三类场景接管
更新记录 (1)
-
v1.1.0
2026-10-17
### 1.1.0 - 新增自由拖拽、旋转校正、点选文字、点选图形、字符识别、随机切换 - 新增旋转容差、字符长度配置 - 旋转图体积优化(约 56KB → 约 9KB) - 完善 GD 缺失、字体缺失、渲染失败时的自动降级 ### 1.0.0 - 首个版本:滑块拼图、点选、数学算式 - 支持登录/注册/找回、发帖、回帖三类场景接管
QQ官方交流群