captcha_check()返回false主因是session未启用、验证码已消耗或大小写不一致。需启用sessioninit中间件、确保验证码单次有效、校验前trim并统一大小写。

captcha_check() 返回 false 不是代码写错了,而是 Session 没通、验证码已用过、或大小写不一致 —— 这三类问题占实际失败场景的 90% 以上。
SessionInit 中间件必须启用,且不能靠手动 session_start()
ThinkPHP 6 默认注释掉了 \think\middleware\SessionInit::class,光在控制器里写 session('test', 'ok') 没用,因为中间件没跑,$_SESSION 根本不会初始化。
检查方法:在任意控制器方法中执行 var_dump(session_id());,输出为空字符串说明 Session 完全未启动。
正确做法:
• 打开 app/middleware.php
• 确保该行未被注释:\think\middleware\SessionInit::class
• 不要在控制器或模板里调用 session_start(),它会被框架忽略
验证码图像必须用 captcha_img() 或正确路由输出
直接在控制器里写 (new \think\captcha\facade\Captcha())->create() 并 return,极易因布局模板中的空格、BOM 或提前 echo 导致 PNG 流损坏(浏览器显示“破损图像”)。
更安全的做法:
• 模板中直接用 {:captcha_img()},它自动生成带时间戳的 <img src="/captcha?_=1747265400">
• 若需自定义路由,必须单独绑定一个无任何额外输出的方法:Route::get('captcha', [\think\captcha\facade\Captcha::class, 'create']);
• 该路由方法体内禁止任何 echo、dump、print_r,连一个换行都不能有
captcha_check() 失败的三个硬性条件
返回 false 几乎从来不是逻辑错误,而是环境/时机断层:
• 用户输入为空或纯空格 —— 前端没 trim(),后端应先处理:$input = trim($data['vcode'] ?? '')
• Session ID 不一致 —— 登录页和提交页跨子域名(如 login.example.com vs www.example.com),或 HTTPS 页面混用 HTTP 资源触发 Mixed Content,导致两次请求携带不同 PHPSESSID
• 验证码已被消耗 —— ThinkPHP 默认一次有效,captcha_check() 成功后自动清空 session 中的值;JS 重复提交、F5 刷新后重试旧值,必然失败
• 补充一点:默认区分大小写,若生成的是 AbC2,用户输 abc2 就会失败;可统一转大写校验:captcha_check(strtoupper($input))
中文验证码要三者齐全,缺一不可
只配 'useZh' => true 是没用的:
• 'useZh' => true(开启中文开关)
• 'zhset' => '登录|注册|验证|安全|确认'(显式提供中文字符集)
• 'font_path' => __DIR__ . '/../public/fonts/simhei.ttf'(绝对路径 + 真实存在的中文字体文件)
注意:bg 必须是 RGB 数组,如 [245, 245, 245],写成 '#f5f5f5' 会导致整个图像空白;HTTPS 站点还需在 config/captcha.php 中显式配置 'url' => '/captcha',避免框架拼出 http:// 前缀触发拦截
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











