PHP 自定义验证码类实现与使用详解
本文介绍如何使用 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 安全防护的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













