验证码问题分四类:gd未启用或字体缺失致空白/500;路由缓存或中间件导致404/跳转;字体权限不足或内存限制致图片异常;session未启动或目录不可写致校验失败。

验证码图片返回空白或 500 错误
直接原因是 thinkphp 调用 imagecreatefromstring 或 imagepng 等 GD 函数失败,但不报错——PHP 默认关闭了 GD 相关错误提示,导致页面只输出空白。常见于 Linux 服务器未启用 GD 扩展,或启用了但缺少字体支持(如中文验证码)。
检查方法:在项目根目录建一个 phpinfo.php,写入 <?php phpinfo(); ?>,访问后搜索 “gd”。若无 GD 模块信息,说明未安装;若有但 “FreeType Support” 显示为 disabled,则中文验证码会出问题(ThinkCaptcha 默认用宋体渲染)。
- Debian/Ubuntu:运行
sudo apt install php-gd,然后重启 PHP-FPM 或 Apache - CentOS/RHEL:运行
sudo yum install php-gd(PHP 7.x)或sudo dnf install php-gd(PHP 8.x) - 确认字体路径:把
simhei.ttf或arial.ttf放到public/static/font/,并在配置中显式指定:'font' => './static/font/simhei.ttf'
验证码请求返回 404 或直接跳转首页
这不是 GD 的问题,而是路由或缓存干扰。ThinkPHP 6 默认开启路由缓存,而验证码 URL(如 /captcha)是通过 Route::rule() 动态注册的,若缓存生成时该规则未被加载,后续请求就找不到对应路由。
典型表现:本地开发正常,部署后首次访问验证码 404,清空 runtime/route 后临时恢复,刷新几次又失效。
- 执行
php think route:clear清除路由缓存 - 检查
app/middleware.php是否对验证码路由误加了中间件(如CheckAuth),导致未登录用户被拦截重定向 - 确认验证码路由定义位置:必须在
app/route/app.php中,且不能包裹在条件判断里(如if (env('APP_DEBUG')) { ... })
验证码图片显示但始终不正确(全黑、乱码、小方块)
大概率是 GD 渲染时无法读取字体文件,或内存/图像尺寸超限。ThinkPHP 的 Captcha 类默认使用 4 字符、120×50 尺寸,若服务器内存限制低(如 memory_limit = 16M),或字体文件权限为 600(仅属主可读),就会降级为纯色块或 ASCII 占位符。
- 检查字体文件权限:
ls -l public/static/font/simhei.ttf,应为-rw-r--r--(644) - 临时调大内存限制:在
public/index.php顶部加ini_set('memory_limit', '32M'); - 简化验证码配置,排除干扰:
'length' => 3, 'width' => 100, 'height' => 40, 'fontSize' => 16, 'font' => './static/font/arial.ttf'
验证码校验始终失败(输入正确也提示“验证码错误”)
核心原因:session 未正常启动或跨请求丢失。ThinkPHP 验证码将真实值存入 session,而校验时 session 数据为空——这通常不是验证码组件的问题,而是部署环境的 session 配置缺失。
尤其注意 Nginx + PHP-FPM 场景:若未显式配置 session.save_path,PHP 可能尝试写入系统临时目录(如 /tmp),而该目录权限不足或被 SELinux 限制。
- 检查
runtime/session目录权限:chmod -R 755 runtime/session,并确认 Web 用户(如www-data或nginx)对其有写权限 - 在
config/app.php中强制指定 session 路径:'session' => [ 'type' => 'file', 'path' => '../runtime/session', ] - 验证 session 是否生效:在控制器中加
session('test', 'ok'); dump(session('test'));,看能否输出'ok'
runtime/session 目录不可写这个更隐蔽的点。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











