PHP 自定义验证码类实现与使用详解

小石头
小石头
发布时间:2026-10-15 | 2人浏览过
原创

本文介绍如何使用 PHP GD 库创建一个可配置的验证码类,涵盖背景、字体、干扰线及雪花效果的生成逻辑,并演示通过 Session 进行前端展示与后端校验的完整流程。

验证码核心逻辑分析

一个安全的验证码通常由随机字符生成、图像渲染(含抗识别干扰)、以及状态持久化三部分组成。以下代码构建了一个名为 ValidateCode 的类,利用 PHP 内置的 GD 库在内存中绘制 PNG 图像。

第1步:定义验证码属性与配置

首先初始化类的私有属性,确定验证码的长度、尺寸、字符集及字体路径。这些参数决定了最终验证码的安全性和视觉样式。

class ValidateCode {
    private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789'; // 去除易混淆字符
    private $code; // 生成的验证码字符串
    private $codelen = 4; // 验证码长度
    private $width = 130; // 图像宽度
    private $height = 50; // 图像高度
    private $img; // 图像资源句柄
    private $font; // 字体文件路径
    private $fontsize = 20; // 字体大小
    private $fontcolor; // 字体颜色

    public function __construct() {
        // 确保字体路径指向正确的 ttf 文件,否则无法渲染文字
        $this->font = dirname(__FILE__).'/font/elephant.ttf';
    }
}

第2步:实现随机字符与图像生成方法

该类包含五个核心私有方法,分别负责背景绘制、字符生成、干扰元素添加和图像输出。理解这些方法的协同工作方式有助于后续定制修改。

  • createBg(): 创建真彩色图像对象,并填充随机浅色背景,防止OCR直接识别前景色差异过大的问题。
  • createCode(): 从白名单字符集中随机抽取指定数量的字符组成验证码字符串。
  • createLine(): 绘制随机的线条和雪花点,增加程序破解难度。注意:过于密集的干扰可能影响用户体验,需根据实际场景平衡。
  • createFont(): 使用 TTF 字体在背景上绘制字符,并通过旋转角度(mt_rand(-30, 30))和微小位移进一步增加识别难度。
  • outPut(): 设置 HTTP 头为图片类型,输出 PNG 格式并在完成后释放内存资源。
// 生成随机码
private function createCode() {
    $_len = strlen($this->charset)-1;
    for ($i=0;$i<$this->codelen;$i++) {
        $this->code .= $this->charset[mt_rand(0,$_len)];
    }
}

// 生成背景
private function createBg() {
    $this->img = imagecreatetruecolor($this->width, $this->height);
    $color = imagecolorallocate($this->img, mt_rand(157,255), mt_rand(157,255), mt_rand(157,255));
    imagefilledrectangle($this->img,0,$this->height,$this->width,0,$color);
}

// 生成线条、雪花(干扰项)
private function createLine() {
    for ($i=0;$i<6;$i++) { // 线条
        $color = imagecolorallocate($this->img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
        imageline($this->img,mt_rand(0,$this->width),mt_rand(0,$this->height),mt_rand(0,$this->width),mt_rand(0,$this->height),$color);
    }
    for ($i=0;$i<100;$i++) { // 雪花
        $color = imagecolorallocate($this->img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255));
        imagestring($this->img,mt_rand(1,5),mt_rand(0,$this->width),mt_rand(0,$this->height),'*',$color);
    }
}

// 生成文字
private function createFont() {
    $_x = $this->width / $this->codelen;
    for ($i=0;$i<$this->codelen;$i++) {
        $this->fontcolor = imagecolorallocate($this->img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
        imagettftext($this->img,$this->fontsize,mt_rand(-30,30),$_x*$i+mt_rand(1,5),$this->height / 1.4,$this->fontcolor,$this->font,$this->code[$i]);
    }
}

// 输出
private function outPut() {
    header('Content-type:image/png');
    imagepng($this->img);
    imagedestroy($this->img);
}

// 对外执行入口
public function doimg() {
    $this->createBg();
    $this->createCode();
    $this->createLine();
    $this->createFont();
    $this->outPut();
}

// 获取验证码内容供校验使用
public function getCode() {
    return strtolower($this->code);
}

此类生成的验证码示例如下:

Session 验证集成流程

仅生成图片不足以构成安全验证,必须将验证码文本存储在服务器端(通常使用 Session),以便在用户提交时进行比对。以下是完整的集成步骤。

第1步:封装验证码处理脚本

新建 captcha.php 文件,实例化验证码类,触发图像生成并将其结果存入 Session。这是前后端交互的关键节点。

<?php
session_start(); // 必须开启会话
require './ValidateCode.class.php'; // 引入类文件,注意调整实际路径

$_vc = new ValidateCode();
$_vc->doimg(); // 输出图片

// 保存生成的验证码到 Session,统一转为小写便于比较
$_SESSION['authnum_session'] = $_vc->getCode();
?>

第2步:前端页面显示与自动刷新

在 HTML 表单中嵌入图片,并利用 JavaScript 实现点击换图。这解决了用户看不清验证码且不希望刷新整个页面的问题。

<!-- 点击图片触发 Math.random() 参数重置 URL,强制浏览器重新请求 captcha.php -->
<img title="点击刷新" src="./captcha.php" align="absbottom" onclick="this.src='captcha.php?'+Math.random();"/>

第3步:后端提交校验

用户输入后,对比 POST 提交的值与 Session 中的值。若匹配则允许继续,否则提示错误。

<?php
session_start();
$validate = "";
if (isset($_POST["validate"])) {
    $validate = $_POST["validate"];
    echo "您刚才输入的是:" . $_POST["validate"] . "<br>状态:";
    
    // 严格区分大小写可能会导致误判,建议统一转为小写再比较
    if (strcasecmp($validate, $_SESSION["authnum_session"]) != 0) {
        echo "<font color=red>输入有误</font>"; 
    } else {
        echo "<font color=green>通过验证</font>"; 
        // 可选:验证通过后销毁当前验证码以防重放攻击
        // unset($_SESSION['authnum_session']);
    }
}
?>

结合上述步骤,即可完成一个具备基本防刷功能的 PHP 验证码系统。该方法利用 GD 库避免了引入第三方大体积组件,适合轻量级项目或特定部署环境。

以上就是 PHP 验证码类编写与 Session 验证实现的详细内容,更多关于 PHP 安全防护的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表