验证码不刷新是因浏览器缓存,需前端加时间戳参数且PHP端加no-cache响应头;空白或乱码因输出前有空格/BOM,须UTF-8无BOM并禁用任何前置输出;校验失败多因Session未正确存储或传递;OCR易识别需优化字符集、干扰线、旋转角度及字体路径。

PHP 生成验证码图片后浏览器不刷新
常见现象是点击“换一张”按钮,src 地址没变,或变了但图片还是旧的——本质是浏览器缓存了 PHP 输出的 PNG/JPEG。不是 PHP 没生成新图,而是前端没让浏览器重新请求。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 给
<img>的src后拼上时间戳或随机数,比如src="captcha.php?t=<?php echo time(); ?>"或src="captcha.php?r=<?php echo rand(); ?>" - PHP 端也要加响应头禁止缓存:
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');和header('Pragma: no-cache'); - 别只依赖前端加参数:有些代理或 CDN 会忽略查询参数,必须服务端明确声明不缓存
验证码图片生成后无法显示(空白或报错)
典型错误是页面一片空白,或出现 Warning: Cannot modify header information,或直接输出一堆乱码。根本原因是 PHP 脚本在输出图片前意外输出了空格、BOM、echo 或错误提示。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 确保验证码 PHP 文件(如
captcha.php)开头**没有任何输出**:无空格、无 BOM、无echo、无print、无var_dump - 调用
imagepng()或imagejpeg()前,必须先输出正确的Content-Type头:header('Content-Type: image/png'); - 如果用了 UTF-8 编码,务必保存为「UTF-8 无 BOM」格式,编辑器里常被忽略
- 临时调试时可在文件开头加
ob_end_clean();清掉已有输出缓冲,但这是补救,不是替代规范编码
点击刷新后验证码校验始终失败
用户看到新图,但输入正确字符仍提示“验证码错误”,问题通常出在 Session 未正确传递或存储逻辑错位。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 生成验证码时,必须用
$_SESSION存储真实值,且确保session_start()在脚本最开头(早于任何输出) - 校验时读取的 key 必须和写入时完全一致,比如写入用
$_SESSION['captcha_code'] = $code;,校验就得用$_SESSION['captcha_code'],不能拼错或大小写不一致 - 避免在验证码生成脚本里调用
session_destroy()或覆盖$_SESSION数组 - 注意:AJAX 刷新时,如果前后端域名/协议/端口不一致,可能导致 Cookie 不带,Session 失效——检查浏览器开发者工具的 Network 请求中 Cookie 是否随请求发出
验证码文字太容易被 OCR 识别或太难看清
太简单会被自动破解,太扭曲又导致人工识别率暴跌。这不是审美问题,是安全与可用性的平衡点。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 字符集避开
0/O/l/1/I等易混淆字母数字,用$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; - 干扰线数量控制在 2–4 条,太多影响识别;干扰点用
imagesetpixel()随机打,密度别超 5% - 文字旋转角度建议 ±15° 内,超过 20° 人眼识别率明显下降
- 字体务必用真型字体(
imagettftext()),别用 GD 默认点阵字;路径要写绝对路径,相对路径在 CLI 或不同入口下容易失效,例如__DIR__ . '/font/arial.ttf'











