ThinkPHP8需通过扩展topthink/think-captcha实现图形验证码,配置须兼顾PHP环境(≥8.1、启用openssl/gd)、手动创建config/captcha.php、中文支持需字体+参数三要素、前后端分离推荐API模式返回key与base64图片、验证须小写比对+即时删缓存+5分钟过期。

一、基础环境准备(国内常见卡点)
国内开发常因扩展未启用或路径错误导致验证码空白或报错:
- 确保 PHP ≥ 8.1,且已启用 openssl 和 gd 扩展(缺一不可):在
php.ini中取消注释这两行:extension=opensslextension=gd - 重启 PHP 服务(如
php think run需先Ctrl+C再重启) - 确认 GD 库支持 PNG/JPEG:
php -r "print_r(gd_info());"查看png_support和jpeg_support是否为 true - Web 服务器(Nginx/Apache)必须指向
public/目录,否则captcha_img()路由无法被正确解析[^1]
二、安装与配置 captcha.php(推荐手动创建)
TP8 不自动创建 config/captcha.php,必须手动建立,否则会报 Class 'think\captcha\Captcha' not found 错误[^2]:
- 在
config/目录下新建captcha.php,内容至少包含:
return [
'length' => 4,
'useNoise' => true,
'useCurve' => true,
'fontSize' => 25,
'bg' => [245, 245, 245], // 必须是 RGB 数组,不能写 '#f5f5f5'
'useZh' => false, // 如需中文,还需设置 zhset 和 fontttf
];
- 若需中文验证码,必须同时满足三项:
'useZh' => true、'zhset' => '登录|验证|安全|防刷'、'fontttf' => __DIR__ . '/../public/fonts/simhei.ttf'(字体文件需真实存在且为 UTF-8 兼容的中文字体)[^3] - HTTPS 站点务必检查
url参数是否设为相对路径(如留空),避免混合内容被浏览器拦截
三、前后端联调关键细节(国内主流 Vue + TP8 场景)
验证码图片需支持点击刷新,且表单提交时携带校验依据:
- 后端提供一个接口(如
/user/captcha),控制器中直接返回:return captcha_img();(传统模式)或$res = Captcha::create(); cache('cap_' . $key, $res['code'], 300); return json(['key' => $key, 'img' => $res['img']]);(API 模式,推荐用于前后端分离)[^4] - 前端 img 标签绑定动态 src:
<img :src="captchaImgUrl" @click="refreshCaptcha" />
其中captchaImgUrl是 computed 属性,拼接时间戳防止缓存:captchaImgUrl() { return '/user/captcha?t=' + this.t; }refreshCaptcha() { this.t = Date.now(); } - 表单提交时,除用户输入的
captcha值外,还应传入对应 key(如 API 模式下后端返回的key),便于后端精准取缓存比对
四、验证逻辑与安全加固(生产必备)
仅比对字符串远远不够,必须结合时效、唯一性和防重放:
立即学习“PHP免费学习笔记(深入)”;
- 验证时统一转小写(避免大小写敏感问题):
$input = strtolower(input('post.captcha'));$stored = strtolower(cache('cap_' . input('post.captcha_key'))); - 验证成功后立即删除缓存:
cache('cap_' . input('post.captcha_key'), null); - 单次有效 + 5 分钟过期是底线,高并发建议用 Redis 替代 file 缓存,避免 session 文件锁竞争[^5]
- 不要依赖客户端传来的 IP 或 User-Agent 做绑定,应以业务标识为主(如手机号哈希、临时 token)



















