ThinkPHP 6.0启用验证码需四步:1. 安装扩展并启用GD;2. 创建UTF-8无BOM的config/captcha.php配置文件;3. 启用Session中间件;4. 正确实现输出与验证接口,HTTPS下需配置url为相对路径。

在ThinkPHP 6.0项目中快速启用可用、可验证、不报错的验证码功能,必须绕过“装了就完事”的误区——缺config/captcha.php会Class not found,HTTPS下不配url会Mixed Content拦截,Session未启用则check()永远返回false,GD扩展未开会导致图片空白。
安装扩展并确认环境就绪
进入项目根目录,执行:composer require topthink/think-captcha。
安装完成后,检查vendor/topthink/think-captcha目录是否存在;若调用时报Class 'think\captcha\Captcha' not found,运行composer dump-autoload刷新自动加载。
【必须确认PHP已启用GD扩展】:在命令行执行php -m | grep gd,无输出则需编辑php.ini取消extension=gd前的分号,并重启Web服务。否则Captcha::create()将静默失败,前端只显示空白或乱码。
立即学习“PHP免费学习笔记(深入)”;
创建并配置captcha.php文件
在config/目录下新建captcha.php,文件编码必须为UTF-8无BOM(VS Code中右下角点击编码→“Save with Encoding”→选UTF-8),内容返回标准数组:
return [ 'length' => 4, 'useNoise' => true, 'useCurve' => true, 'fontSize' => 28, 'imageW' => 180, 'imageH' => 60, 'expire' => 1800, 'useZh' => false ];
注意:文件名和路径必须严格为config/captcha.php,框架不会识别captcha_config.php或config/captcha/index.php等变体;该文件不存在时,所有Captcha类初始化均会中断并抛出类未定义错误,而非配置缺失提示。
启用Session中间件
打开app/middleware.php,找到这一行:// \think\middleware\SessionInit::class。
删掉开头的//,使其变为:\think\middleware\SessionInit::class。
这一步不可跳过——TP6默认关闭Session初始化,而验证码校验依赖Session存储原始值;未启用时,captcha_check()始终返回false,且无任何警告日志。
编写验证码输出接口
在控制器(如app/controller/Index.php)中添加方法:
use think\captcha\facade\Captcha;
public function captcha() { return Captcha::create(); }
该方法体内禁止任何输出:不能有echo、var_dump、Log::info(),连方法前多一个空行或UTF-8 BOM都可能触发“headers already sent”,导致图片流被破坏。
路由需显式绑定:在config/route.php中添加get('captcha', 'index/captcha');,确保请求/captcha能精准命中该方法。
前端模板中显示验证码
方法一(推荐):直接使用助手函数:{:captcha_img()}——自动生成带点击刷新功能的<img>标签,无需额外写JS。
方法二(手动控制URL):<img src="{:url('index/captcha')}" onclick="this.src='{:url('index/captcha')}?'+Math.random()" title="点击换图">。
⚠️ 若用方法二,必须提前在路由中定义index/captcha对应的方法,否则404;且HTTPS站点下,captcha_img()默认生成http://链接,浏览器将拦截Mixed Content——此时需在captcha.php中强制添加'url' => '/captcha'(相对路径)。
服务端验证用户输入
第一步:接收表单数据,例如$data = $this->request->param();。
第二步:调用验证函数:if (!captcha_check($data['captcha'])) { $this->error('验证码错误,请重新输入'); }。
第三步:验证通过后,验证码自动失效(Session或Redis中对应key被删除);若验证失败,切勿合并提示“用户名或密码错误”,应单独返回“验证码错误”,防止信息泄露。
注意:captcha_check()内部已对输入字符串执行strtolower(),因此前端无需做大小写转换,传入原样即可。
适配前后端分离场景(Redis替代Session)
当项目采用Vue/React + API模式时,原生Session无法跨域共享,必须切换存储机制。
① 在config/captcha.php中禁用Session存储,添加'store' => 'redis'(需确保Redis已配置并启用)。
② 接口返回验证码时,不再只返回图片流,而是先生成并缓存:$code = Captcha::create()->code; $uuid = Str::uuid()->toString(); cache('captcha_'.$uuid, $code, 300);,再返回['uuid' => $uuid, 'img' => 'data:image/png;base64,...']。
③ 登录接口接收uuid与用户输入captcha,比对逻辑为:strtolower($input) === strtolower(cache('captcha_'.$uuid)),比对成功后立即执行cache('captcha_'.$uuid, null)清除。
这一步操作起来很简单,直接替换底层存储驱动即可,无需重写业务逻辑,兼容原有captcha_check()调用习惯。



















