动态GIF验证码通过多帧动画展示不断变化的字符,能有效提升机器识别的难度,PHP可以借助GD库实现这类验证码的生成,核心逻辑是逐帧绘制不同状态的验证码内容,再将多帧合并为GIF动画输出。

环境准备
首先需要确保PHP环境已经安装并启用了GD库,可以通过phpinfo()函数查看是否存在GD扩展,若未安装可以根据服务器系统执行对应的安装命令,比如Ubuntu系统可以运行sudo apt-get install php-gd后重启PHP服务。
核心实现步骤
1. 初始化GIF动画生成器
PHP的GD库提供了imagegif()函数可以输出GIF图像,我们可以通过输出缓冲区收集每一帧的内容,再拼接为完整的GIF动画。首先需要定义验证码的基础参数:
<?php
// 验证码参数配置
$config = [
'width' => 200, // 验证码宽度
'height' => 80, // 验证码高度
'length' => 4, // 验证码字符长度
'font_size' => 30, // 字体大小
'frame_count' => 5, // 动画总帧数
'frame_delay' => 20, // 每帧延迟时间(百分之一秒)
'chars' => 'abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789' // 可选字符集
];
// 生成随机验证码字符串
function generateCaptchaStr($length, $chars) {
$str = '';
$char_len = strlen($chars) - 1;
for ($i = 0; $i < $length; $i++) {
$str .= $chars[rand(0, $char_len)];
}
return $str;
}
$captcha_str = generateCaptchaStr($config['length'], $config['chars']);
// 将验证码字符串存入session,用于后续验证
session_start();
$_SESSION['captcha'] = $captcha_str;
?>
2. 逐帧绘制验证码内容
每一帧的验证码字符可以有轻微的位置、颜色、旋转角度变化,模拟动态效果,绘制完成后将帧内容存入缓冲区:
<?php
// 开启输出缓冲区收集GIF帧
ob_start();
// 加载字体文件,这里使用GD库内置的字体,也可以自定义字体路径
// 自定义字体示例:$font_path = 'path/to/font.ttf';
for ($frame = 0; $frame < $config['frame_count']; $frame++) {
// 创建画布
$img = imagecreate($config['width'], $config['height']);
// 分配背景色(浅色)
$bg_color = imagecolorallocate($img, 245, 245, 245);
// 分配文字颜色(随机深色)
$text_color = imagecolorallocate($img, rand(0, 100), rand(0, 100), rand(0, 100));
// 分配干扰线颜色
$line_color = imagecolorallocate($img, rand(150, 200), rand(150, 200), rand(150, 200));
// 绘制随机干扰线
for ($i = 0; $i < 3; $i++) {
imageline($img, rand(0, $config['width']), rand(0, $config['height']), rand(0, $config['width']), rand(0, $config['height']), $line_color);
}
// 绘制每个字符,每帧有轻微偏移和旋转
for ($i = 0; $i < $config['length']; $i++) {
$char = $captcha_str[$i];
// 每帧字符的x坐标有1-2像素的随机偏移
$x = 20 + $i * 40 + rand(-2, 2);
// 每帧字符的y坐标有1-2像素的随机偏移
$y = 50 + rand(-2, 2);
// 每帧字符有-10到10度的随机旋转角度
$angle = rand(-10, 10);
// 使用内置字体绘制,若用自定义字体可替换为imagettftext
imagestring($img, 5, $x, $y, $char, $text_color);
// 自定义字体绘制示例(需要开启FreeType支持)
// imagettftext($img, $config['font_size'], $angle, $x, $y, $text_color, $font_path, $char);
}
// 绘制干扰点
for ($i = 0; $i < 50; $i++) {
imagesetpixel($img, rand(0, $config['width']), rand(0, $config['height']), $text_color);
}
// 输出当前帧到缓冲区
imagegif($img);
// 销毁当前画布释放内存
imagedestroy($img);
// 如果不是最后一帧,添加帧延迟标识
if ($frame != $config['frame_count'] - 1) {
echo '<?GIF89a'; // GIF帧分隔标识
echo pack('C*', $config['frame_delay'], $config['frame_delay']); // 延迟时间
}
}
// 获取缓冲区内容并清空
$gif_content = ob_get_clean();
// 设置HTTP响应头为GIF图像
header('Content-Type: image/gif');
// 输出最终GIF动画
echo $gif_content;
?>
3. 验证码验证实现
用户提交表单后,对比输入的验证码和session中存储的字符串即可完成验证:
<?php
session_start();
if (isset($_POST['captcha_input'])) {
$input = strtolower(trim($_POST['captcha_input']));
$correct = strtolower($_SESSION['captcha'] ?? '');
if ($input === $correct) {
echo '验证码验证通过';
// 验证通过后销毁session中的验证码
unset($_SESSION['captcha']);
} else {
echo '验证码错误,请重新输入';
}
}
?>
注意事项
- 每帧的字符变化幅度不要过大,否则用户难以识别,建议偏移范围控制在正负3像素以内,旋转角度控制在正负15度以内。
- 干扰线和干扰点的数量要适中,过多会影响用户识别,过少则容易被机器破解。
- 生成的GIF动画体积不要过大,建议帧数控制在3-8帧,单帧尺寸不要超过300*100像素,避免影响页面加载速度。
- 验证码字符串建议定期更新,验证通过后及时销毁session中的存储内容,避免被重复使用。
PHPGIF_animationcaptchaimagecreate修改时间:2026-06-18 21:42:25