thinkphp 5.1+ 验证码非内置,必须安装 topthink/think-captcha 扩展并启用 session 中间件,否则 create() 返回空白、check() 恒为 false;session 未生效或 gd 库缺失是图像空白主因,captcha_img() 是最稳妥的前端嵌入方式。

ThinkPHP 5.1+ 的验证码不是内置功能,不装 topthink/think-captcha 扩展、不启用 Session 中间件,create() 一定返回空白,check() 恒为 false —— 这不是代码写错了,是环境没配好。
安装扩展和启用 Session 是硬前提
TP5.1 开始,验证码被抽成独立扩展,必须手动安装。光 composer require topthink/think-captcha 不够,还必须确保 Session 能正常读写,否则验证码值根本存不进、也取不出。
- 执行
composer require topthink/think-captcha,确认vendor/topthink/think-captcha目录存在 - 检查
app/middleware.php:TP6 默认注释掉了\think\middleware\SessionInit::class,TP5.1 需确认该行已取消注释;若用闭包路由或自定义中间件堆栈,也要确保它在请求生命周期早期执行 - 快速验证 Session 是否生效:在任意控制器方法里写
session('test', 'ok'); var_dump(session('test'));,输出string(2) "ok"才算通过 - 不要在控制器里手动调用
session_start()—— ThinkPHP 的 Session 必须由中间件统一初始化,否则$_SESSION和框架 session() 函数不同步
captcha_img() 是最稳的前端嵌入方式
直接在模板里写 {:captcha_img()},比手拼 <img src="/captcha"> 少踩 80% 的坑。它自动处理随机参数防缓存、自动适配 URL 路由模式(PATHINFO / 兼容模式),且不依赖你额外定义路由。
- 如果用了自定义路由前缀(比如
Route::domain('admin')->group(...)),captcha_img()仍能生成正确路径;手写/captcha很可能 404 - 点击刷新只需加一行 JS:
onclick="this.src='{:captcha_src()}?'+Math.random()",captcha_src()返回的是纯 URL 字符串,适合拼接 - 不要在生成验证码的控制器方法里做任何
echo、var_dump或布局模板输出 —— 一个空格或换行都会破坏 PNG 流,浏览器显示“损坏的图像”
check() 失败几乎都不是逻辑问题
(new \think\captcha\Captcha())->check($input) 返回 false,90% 是因为环境或调用时机不对,而不是字符串比对失败。
- 前端输入未
trim():用户多敲一个空格,check()就失败;建议统一$input = trim($input)再校验 - Session ID 不一致:登录页和提交页跨子域(如
login.example.comvswww.example.com)、或前后端域名不统一,导致两次请求用的不是同一个 Session;检查session_id()在两处是否相同 - 验证码已被消耗:ThinkPHP 默认一次有效,
check()成功后立刻从 Session 清除原始值;JS 重复提交、F5 刷新后重试旧值,必然失败 - 大小写敏感:默认配置下区分大小写;若前端输入全小写但图片生成的是大写字母,要么前端统一转大写,要么配置
'useZh' => false, 'useCurve' => true并设'codeSet' => '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'控制字符集
自定义配置别只改外观,要兼顾安全与可用性
改字体大小、长度这些只是表层;真正影响防刷效果的是干扰策略和有效期控制。
-
'useNoise' => true和'useCurve' => true必开 —— 去掉噪点和曲线,OCR 识别率会飙升 -
'expire' => 300(单位秒)建议显式设置,避免依赖 PHP 默认 session.gc_maxlifetime;过长(如 3600)易被暴力穷举,过短(如 60)影响用户体验 - 不要把配置数组硬编码在每个控制器里;推荐新建
config/captcha.php(TP5.1 放application/extra/captcha.php),内容为return ['length' => 4, 'useNoise' => true, ...];,框架会自动合并 - 若需多组验证码(如登录页 + 注册页独立校验),用
captcha_img('login')和captcha_check($input, 'login'),ID 不同则 Session 存储 key 分离,互不干扰
最常被忽略的一点:验证码图像依赖 GD 库,但错误提示往往静默——create() 返回空白时,先看 PHP 是否启用了 gd 扩展(php -m | grep gd),再检查 imagepng() 或 imagejpeg() 是否被禁用(某些共享主机限制)。没有报错不等于没问题,图像流中断就是无声失败。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











