先检查gd_info()是否启用:若报错或返回false,说明GD扩展未加载,需启用php.ini中的extension=gd;若jpeg为false,则验证码配置改为'type' => 'png';若output_compression为true,需关闭zlib.output_compression。

验证码图片空白或报500错误,先查gd_info()是否启用
ThinkPHP 验证码依赖 GD 库生成图像,如果页面显示空白、返回空响应或直接 500 错误,大概率是 GD 扩展没开或功能不全。别急着改控制器逻辑,先确认底层支持。
在任意可执行 PHP 脚本里加一行:
print_r(gd_info());
,看输出中 GD Version 是否存在、png/jpeg 相关键是否为 true。常见坑是 Docker 或某些精简版 PHP 容器默认不装 php-gd,或只启用了部分格式(比如支持 PNG 但禁了 JPEG,而 ThinkPHP 默认用 JPEG)。
- 若
gd_info()报错或返回false:说明 GD 扩展未加载,检查php.ini中是否启用extension=gd(Linux)或extension=php_gd2.dll(Windows) - 若
jpeg为false:改验证码配置,强制用 PNG:'type' => 'png'
- 若
output_compression为true:可能干扰图像二进制输出,临时关闭:ini_set('zlib.output_compression', 'Off');
验证码不刷新或始终提示“错误”,盯紧session_start()时机和存储路径
ThinkPHP 验证码靠 Session 存储真实值,如果每次输入都报错、F5 刷新后值不变、或者多标签页互相干扰,问题几乎一定出在 Session 初始化或写入环节。
关键点不是“有没有开启 Session”,而是“它是否在验证码生成前就已启动且可写”。ThinkPHP 5.1+ 默认自动启动 Session,但如果你在中间件、钩子或自定义函数里提前调用了 ob_start()、header() 或输出了任何空格/换行,Session 就会静默失败。
- 检查入口文件
public/index.php或配置文件config/session.php中type是否为file,并确认save_path目录存在、Web 用户有写权限(如chmod 755 runtime/session) - 在验证码生成方法(如
captcha操作)开头加一行:var_dump(session_status() === PHP_SESSION_ACTIVE);
,如果不是true,说明 Session 根本没活起来 - 避免在验证码路由前触发任何
echo、print、var_dump(包括末尾空行),哪怕只是?> 之间的换行也会让 Session header 失效
验证码字体不显示或乱码,确认ttf路径和编码一致性
ThinkPHP 默认用 think-captcha 的内置字体,但如果自定义了 font 配置项,或升级后字体路径变更,就会出现方块、问号或干脆不渲染文字。
核心问题是:GD 加载字体时对路径敏感、对文件编码无感——它只认二进制 TTF 文件,且路径必须能被 PHP 进程直接读取(不能是 URL,也不能是相对路径未解析到位)。
- 检查配置中
font值是否为绝对路径,例如:/var/www/thinkphp/public/static/font/arial.ttf
,而非./static/font/arial.ttf - 用
file_exists()和is_readable()实测该路径:var_dump(file_exists($fontPath), is_readable($fontPath));
- 不要用中文命名的字体文件,GD 对 UTF-8 文件名支持不稳定;也不要用 Windows 下带 BOM 的 TXT 改名来的 TTF(实际是文本)
- 如果用的是 ThinkPHP 6 +
topthink/think-captchav3+,注意它默认不再自带字体,需手动放一个合法 TTF 到项目目录并显式配置
本地正常上线就失效,重点比对session.cookie_httponly和session.use_cookies
开发环境验证码好好的,一上 Nginx/Apache 就 404 或跨域丢失,往往不是代码问题,而是服务器级 Session 策略和前端 Cookie 行为不匹配。
典型表现是:登录页能显示验证码,但提交时总提示“验证码错误”,抓包发现请求头里没带 PHPSESSID Cookie。这时候要查 PHP 的 Session 发送策略是否被服务器覆盖。
- 检查
phpinfo()输出中session.cookie_httponly是否为On:如果是,确保前端 JS 不试图读取该 Cookie(正常情况也不该读) - 确认
session.use_cookies是On(否则靠 URL 传 ID,极不安全且易失效) - 如果用了反向代理(如 Nginx),检查是否透传了
Cookie头:proxy_pass_request_headers on;
,并确认fastcgi_param HTTP_COOKIE $http_cookie;存在 - HTTPS 站点下,若
session.cookie_secure为On但访问的是 HTTP,Cookie 就不会下发——临时改成Off测试,再按需调整
GD 和 Session 看似基础,但它们卡在输出流最底层,一旦出问题,现象千奇百怪,排查时容易陷入业务逻辑打转。盯住 gd_info() 返回值、session_status() 状态、字体文件真实可读性、以及服务器层 Cookie 控制开关,四点对齐,90% 的验证码异常就定位完了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










