PHP生成验证码的三种常用方法:从简单到健壮
分享几段实用的PHP验证码函数代码,分别适用于不同安全需求的场景。内容涵盖基础字母数字组合、十六进制混淆以及带有线条和雪花干扰的增强型验证方式,所有代码均支持自定义尺寸与数量。
结果或目标
在Web应用中引入图形验证码以拦截自动化脚本,需要根据业务安全性选择合适的实现层级。以下提供了三个层级的PHP实现方案:
- 基础版:纯随机字符组合,无干扰,适合低流量或非敏感页面。
- 进阶版:使用十六进制混合随机线条,兼顾美观与安全。
- 健壮版:加入边框、动态线条与“雪花”噪点,并通过
ob_clean()确保输出纯净,适合登录、注册等关键接口。
准备条件
- 环境要求:服务器需安装PHP并启用GD库(处理图像函数依赖),确保已开启
session支持以存储验证码值供后续校验。 - 路径管理:若需将验证码保存为图片文件而非直接输出,需移除代码中输出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图像处理与安全的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









