PHP生成验证码的三种常用方法:从简单到健壮

沈知远
沈知远
发布时间:2026-10-13| 4人浏览过
原创

分享几段实用的PHP验证码函数代码,分别适用于不同安全需求的场景。内容涵盖基础字母数字组合、十六进制混淆以及带有线条和雪花干扰的增强型验证方式,所有代码均支持自定义尺寸与数量。

结果或目标

在Web应用中引入图形验证码以拦截自动化脚本,需要根据业务安全性选择合适的实现层级。以下提供了三个层级的PHP实现方案:

  • 基础版:纯随机字符组合,无干扰,适合低流量或非敏感页面。
  • 进阶版:使用十六进制混合随机线条,兼顾美观与安全。
  • 健壮版:加入边框、动态线条与“雪花”噪点,并通过ob_clean()确保输出纯净,适合登录、注册等关键接口。

准备条件

  1. 环境要求:服务器需安装PHP并启用GD库(处理图像函数依赖),确保已开启session支持以存储验证码值供后续校验。
  2. 路径管理:若需将验证码保存为图片文件而非直接输出,需移除代码中输出Header的部分并替换为imagepng($img, 'path/to/file.png');操作。

真实操作顺序

第1步:使用简单函数生成基础验证码

此方法直接拼接大小写字母与数字,并随机选择四个字符绘制在白色背景上。虽然缺乏复杂的干扰元素,但逻辑最简单,易于二次开发。

<?php
function code() {
    // 创建画布
    $im = imagecreatetruecolor(100, 40);
    // 分配颜色:黑色、白色及随机干扰色
    $black = imagecolorallocate($im, 0, 0, 0);
    $white = imagecolorallocate($im, 255, 255, 255);
    
    // 填充背景
    imagefill($im, 0, 0, $white);
    
    // 构造字符池并打乱排序
    $strarr = array_merge(range(0,9), range('a','z'), range('A','Z'));
    shuffle($strarr);
    $str = join(array_slice($strarr, 0, 4));
    
    // 绘制随机颜色的验证码字符串
    $mm = rand(0, 40);
    $color1 = imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
    imagestring($im, 5, $mm, 10, $str, $color1);
    
    // 添加像素噪点与直线干扰
    for($i=0; $i<700; $i++) {
        imagesetpixel($im, rand(0, 100), rand(0, 40), imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255)));
    }
    for($t=0; $t<3; $t++) {
        imageline($im, rand(0, 100), rand(0, 40), rand(0, 100), rand(0, 40), imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255)));
    }
    
    // 输出图像
    header("Content-Type: image/png");
    imagepng($im);
}
code();
?>

第2步:使用中等复杂度函数增强安全性

该版本采用十六进制dechex(mt_rand())生成验证码,增加了视觉识别难度。同时加入了灰色边框和多条浅色干扰线,有效防止简单的OCR扫描。

function _code($_code_length = 4, $_width = 75, $_height = 25) {
    // 生成随机十六进制串并存入Session
    for($i=0; $i<$_code_length; $i++) {
        $_nmsg .= dechex(mt_rand(0, 15));
    }
    $_SESSION["code"] = $_nmsg;
    
    // 初始化画布与背景
    $_img = imagecreatetruecolor($_width, $_height);
    $_white = imagecolorallocate($_img, 250, 250, 250);
    imagefill($_img, 0, 0, $_white);
    imagerectangle($_img, 0, 0, $_width-1, $_height-1, imagecolorallocate($_img, 196, 196, 196));
    
    // 绘制干扰线条
    for ($i=0; $i < 6; $i++) {
        imageline($_img, mt_rand(0,$_width), mt_rand(0, $_height), mt_rand(0,$_width), mt_rand(0, $_height), 
            imagecolorallocate($_img, mt_rand(200,255), mt_rand(200,255), mt_rand(200,255)));
    }
    
    // 绘制验证码字符
    for ($i=0; $i < $_code_length ; $i++) {
        imagestring($_img, 5, $i * $_width/$_code_length + mt_rand(1, 10), mt_rand(1, $_height/2), 
            $_SESSION["code"][$i], imagecolorallocate($_img, mt_rand(0,102), mt_rand(0,102), mt_rand(0,102)));
    }
    
    header("Content-Type:image/png");
    imagepng($_img);
    imagedestroy($_img);
}

第3步:使用健壮函数集成完整干扰效果

这是功能最完善的版本,引入了雪花噪点(*号字符随机分布)以及显式的ob_clean()清理缓冲。这能防止因头部信息泄漏导致的PNG解码错误,建议生产环境优先使用。

/*@ captcha()函数的功能:生成高质量验证码
 * @ 可自定义参数:$width, $high, $num(个数), $line_num(线条数), $snow_num(雪花数)
 */
function captcha($width=80, $high=25, $num=4, $line_num=10, $snow_num=50) {
    header('Content-Type: image/png');
    session_start();
    
    // 生成随机数字加字母混合串(此处仍用十六进制演示,可按需修改为alphanumeric)
    for($a = 0; $a < $num; $a++) {
        $code .= dechex(mt_rand(0, 15));
    }
    $_SESSION['captcha'] = $code;
    
    // 创建画布并填充背景
    $img = imagecreatetruecolor($width, $high);
    $backcolor = imagecolorallocate($img, 255, 255, 255);
    imagefill($img, 0, 0, $backcolor);
    
    // 绘制黑色边框
    $bordercolor = imagecolorallocate($img, 0, 0, 0);
    imagerectangle($img, 0, 0, $width-1, $high-1, $bordercolor);
    
    // 随机画线条干扰
    for($i=0; $i<$line_num; $i++) {
        imageline($img, mt_rand(0, $width*0.1), mt_rand(0, $high), 
            mt_rand($width*0.9, $width), mt_rand(0, $high),
            imagecolorallocate($img, mt_rand(150, 255), mt_rand(150, 255), mt_rand(150, 255)));
    }
    
    // 随机撒雪花噪点
    for ($i=0; $i<$snow_num; $i++) {
        imagechar($img, 1, mt_rand(0, $width), mt_rand(0, $high), '*',
            imagecolorallocate($img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255)));
    }
    
    // 绘制验证码文本
    for ($b = 0; $b < strlen($_SESSION['captcha']); $b++) {
        imagechar($img, 5, $b*$width/$num + mt_rand(5, 10), mt_rand(2, $high/2),
            $_SESSION['captcha'][$b], imagecolorallocate($img, mt_rand(10, 150), mt_rand(10, 150), mt_rand(0, 100)));
    }
    
    ob_clean(); // 清除输出缓冲区,防止破坏图像流
    imagepng($img);
    imagedestroy($img);
}

完成判断

  • 直接在浏览器访问包含上述代码的PHP文件,应显示一张PNG格式的图片。
  • 检查浏览器的开发者工具 → Network面板,确认响应的MIME类型为image/png且HTTP状态码为200。
  • 刷新页面多次,观察验证码字符是否变化,且字符周围存在相应的噪点或线条干扰。

原文有依据的排错

  • PNG损坏问题:如果在查看图片时浏览器报错,通常是因为PHP输出前有空行或空格。在第三个代码段中专门使用了ob_clean();来解决此问题,请确保代码开始前没有多余的空白字符。
  • 乱码显示:如果生成的文字是方块或问号,通常是PHP未正确引用中文字体(虽然本示例使用的是系统内置字体,但若更换字体需注意编码一致)。目前使用的imagestring与imagechar配合系统默认字体,对ASCII/十六进制字符支持良好。

简要总结

以上三段代码展示了PHP验证码从简易到专业的演变过程。简单版适合轻量级应用,而第三段集成了完整的干扰项与缓冲清理机制,更适合对外提供服务。以上就是关于PHP验证码实现的详细内容,更多关于PHP图像处理与安全的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。