php 8生成随机验证码图片需启用gd扩展、用random_int生成字符、gd内置字体绘图、加干扰线与噪点、输出png并防缓存。

PHP 8 中生成随机验证码图片,核心是结合 GD 库绘制文字与干扰元素,并将结果以 PNG/JPEG 格式输出。关键点在于:启用 GD 扩展、生成随机字符串、设置字体路径、抗锯齿渲染、添加噪点或干扰线、防止缓存。
1. 确保 GD 扩展已启用
PHP 8 默认不强制启用 GD,需确认 php.ini 中已开启:
- Linux/macOS:检查 extension=gd 是否取消注释
- Windows:确认 php_gd2.dll 已加载(
php -m | grep gd或phpinfo()查看) - 若未启用,安装命令示例(Ubuntu):
sudo apt install php-gd && sudo systemctl restart apache2
2. 生成带干扰的验证码图像(完整可运行代码)
以下是一个兼容 PHP 8 的轻量级实现(无需第三方库),支持中文需额外字体,此处以英文+数字为例:
<?php // 验证码长度与字符集
$length = 4;
$chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= $chars[random_int(0, strlen($chars) - 1)];
}
<p>// 创建画布(宽120×高40)
$width = 120;
$height = 40;
$image = imagecreatetruecolor($width, $height);<p>// 分配颜色
$bg = imagecolorallocate($image, 240, 240, 240); // 浅灰背景
$textColor = imagecolorallocate($image, 50, 50, 50); // 深灰文字
$lineColor = imagecolorallocate($image, 200, 200, 200); // 干扰线色</p><p>// 填充背景
imagefill($image, 0, 0, $bg);</p><p>// 添加少量干扰线(2~4条)
for ($i = 0; $i </p><p>// 添加微小噪点(约100个)
for ($i = 0; $i </p><p>// 使用内置字体(避免依赖外部 .ttf)——更可靠
// 若需更好效果,可换用自定义字体(见下节)
$font = 5; // GD 内置字体编号(1–5),5 最大
$x = 20;
$y = 28;
for ($i = 0; $i </p><p>// 输出 PNG 图像(注意:必须在任何输出前调用)
header('Content-Type: image/png');
imagepng($image);</p><p>// 清理资源
imagedestroy($image);</p><p>// 可选:将验证码存入 session 供后续验证(需先 session_start())
// $_SESSION['captcha_code'] = strtolower($code);
?></p>
3. 如需支持中文或自定义字体
GD 绘制中文必须使用 TrueType 字体(.ttf),且确保字体文件存在、有读取权限:
- 下载免费中文字体(如 simhei.ttf 或 NotoSansCJK
- 替换绘图部分为
imagettftext(),例如:
$fontFile = __DIR__ . '/simhei.ttf'; imagettftext($image, 16, random_int(-10, 10), $x + $i * 24, $y + $y_offset, $textColor, $fontFile, $char);
⚠️ 注意:imagettftext() 在部分精简版 GD(如 Alpine Linux 的 php-gd)中可能被禁用,部署前务必测试。
4. 安全与实用建议
- 验证码值应存入 $_SESSION(非 Cookie 或 GET 参数),并立即生成后销毁旧值
- 响应头添加防缓存:
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); - 前端 img 标签加时间戳防止浏览器缓存:
<img src="captcha.php?<?php%20echo%20time();%20?>"> - 避免使用易混淆字符(如 0/O、1/l/I),已在示例字符集中剔除
- PHP 8 推荐用
random_int()替代rand()或mt_rand(),更安全
不复杂但容易忽略:每次请求必须生成新验证码、服务端严格比对 session 中的原始值(区分大小写或统一转小写)、验证后及时 unset session 中的 code。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











