验证码在thinkphp5中需装扩展、启用session中间件、走纯净输出流三者缺一不可;否则create()返回空白、check()恒为false。

验证码在 ThinkPHP5 中不是内置功能,必须装扩展、启用 Session、走纯净输出流,三者缺一不可;否则 create() 返回空白、check() 恒为 false——这不是代码写错了,是环境没搭好。
必须先装扩展并启用 Session 中间件
TP5.1 起验证码被抽离为独立扩展,不装包、不启中间件,整个流程就卡死。常见错误现象:浏览器显示“损坏的图像”或返回空响应,captcha_check() 总是 false。
- 执行
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"才算通过
生成验证码必须走纯净输出流
验证码图像是二进制 PNG 流,任何额外输出(空格、换行、echo、var_dump)都会破坏流结构,导致浏览器报“损坏的图像”。
- 最稳妥方式是在模板中直接写
{:captcha_img()},它自动生成带时间戳防缓存的<img src="/captcha?_=1717603200"> - 若需自定义路由,必须绑定到纯输出方法,例如:
Route::get('captcha', [\think\captcha\facade\Captcha::class, 'create']); - 若手动调用
(new Captcha())->create(),确保该方法是响应体唯一内容,不能有任何布局模板、前置echo或调试语句
校验失败九成不是比对逻辑问题
captcha_check($input) 返回 false,极少因为“字符串不等”,更多是底层支撑失效。
- 前端输入未
trim():用户多敲一个空格或回车就失败,建议统一$input = trim($input)再校验 - Session ID 不一致:登录页域名是
login.example.com,提交页是www.example.com,跨子域或协议不一致(http/https)都会导致两次请求用不同 Session - 验证码已被消耗:默认一次有效,
check()成功后自动清除 Session 值;JS 重复提交、刷新页面后重试旧值,必然失败 - 大小写敏感:默认区分大小写,若前端转小写而服务端生成大写字母,就会不匹配;可配置
'useZh' => false, 'codeSet' => '0123456789'控制字符集,避免意外混入大小写
配置项差异直接影响可用性与安全性
配置不是可有可无的装饰,几个关键参数直接决定验证码能否正常加载、是否易被绕过。
-
'length' => 4:位数太少(如 3)易暴力穷举;太多(如 6+)影响用户体验,推荐 4–5 -
'useNoise' => true和'useCurve' => true:关闭后图形过于干净,OCR 识别率飙升;生产环境务必开启 -
'expire' => 300:单位秒,超时后 Session 中值自动失效;不设或设太大(如 3600)会拖慢 Session 清理,也增加重放风险 -
'reset' => true:校验成功后自动重置,防止同一码多次使用;若设为false,需自行控制生命周期,容易出安全漏洞
最容易被忽略的是 Session 初始化时机和跨域一致性——哪怕配置全对、代码全抄,只要中间件没启用或域名协议不统一,验证码就永远“看起来对、实际上废”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











