thinkphp5验证码非内置,须安装topthink/think-captcha扩展并启用session中间件,否则create()返回空白、check()恒为false;图像生成依赖gd库和纯净输出流,校验失败多因session失效、输入未trim或验证码已消耗。

ThinkPHP5验证码不是内置功能,而是依赖扩展包 topthink/think-captcha 和 Session 机制协同工作的安全组件。它的核心原理是:后端用 GD 库生成一张含随机字符的图片,并把原始字符串存入当前 Session;前端展示图片并接收用户输入;提交时比对用户输入与 Session 中存储的值是否一致。整个流程成败关键不在代码逻辑,而在环境配置和调用时机。
必须装扩展 + 启用 Session 中间件
TP5.1 起验证码被抽离为独立扩展,不安装、不启用 Session,create() 返回空白、check() 恒为 false——这不是 bug,是前提没满足。
- 执行
composer require topthink/think-captcha,确认vendor/topthink/think-captcha目录存在 - 检查
app/middleware.php是否启用\think\middleware\SessionInit::class(TP6 默认注释掉,需手动取消注释) - 不要在控制器里调用
session_start(),ThinkPHP 的 Session 必须由中间件统一初始化,否则$_SESSION和框架session()不同步 - 快速验证 Session 是否生效:
session('test', 'ok'); var_dump(session('test'));输出string(2) "ok"才算通过
图像生成要走标准输出流,别手动 echo
验证码图像是二进制 PNG/JPEG 流,任何额外输出(空格、换行、echo、var_dump)都会破坏流结构,导致浏览器显示“损坏的图像”。
- 最稳妥方式是模板中直接写
{:captcha_img()},它自动生成带时间戳防缓存的<img src="/captcha?_=1717603200"> - 若需自定义路由,必须绑定到纯输出方法,例如:
Route::get('captcha', [\think\captcha\facade\Captcha::class, 'create']); - 若手动调用
(new Captcha())->create(),确保该方法是响应体唯一内容,不能有任何布局模板或前置输出
校验失败九成是环境或调用问题,不是比对逻辑错
check($input) 返回 false,极少因为“字符串不等”,更多是底层支撑失效。
- 前端输入未
trim():用户多敲一个空格或回车就失败,建议统一$input = trim($input)再校验 - Session ID 不一致:登录页域名是
login.example.com,提交页是www.example.com,跨子域或协议不一致(http/https)都会导致两次请求用不同 Session - 验证码已被消耗:默认一次有效,
check()成功后自动清除 Session 值;JS 重复提交、刷新页面后重试旧值,必然失败 - 大小写敏感:默认区分大小写,若前端转小写而服务端生成大写字母,可统一转大写再比对,或配置
'useZh' => false等参数调整行为
配置灵活但需注意默认行为
验证码类支持传入配置数组定制外观与行为,但部分选项影响安全性或兼容性,需按需开启。
- 增强识别难度:
'useNoise' => true(加噪点)、'useCurve' => true(画干扰曲线)、'fontSize' => 22(加大字体) - 控制有效期:
'expire' => 300(单位秒,5 分钟后自动失效) - 字符类型选择:
'length' => 4(位数)、'useZh' => false(禁用中文,避免字体缺失报错) - 图像尺寸适配:
'imageW' => 130、'imageH' => 45,避免移动端显示过小或溢出
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











