PHP编写验证码的过程主要涉及图像生成、随机字符生成、干扰元素添加以及与前端表单的交互验证,下面将详细介绍实现步骤,包括基础验证码、GD库操作、Session存储验证码值以及前端表单提交验证等关键环节。

验证码的基本原理
验证码的主要目的是区分用户是计算机还是人,防止恶意程序自动提交表单,其核心流程包括:服务器生成随机字符串并绘制成图像,将字符串存储在Session中,用户提交表单时将输入值与Session中的值进行比对,验证通过则允许操作,否则提示错误。
环境准备
PHP生成验证码主要依赖GD库,确保服务器已安装并启用GD库,通过phpinfo()函数检查GD Support是否为enabled,若未启用,可在php.ini中取消;extension=gd前的分号并重启服务。
生成随机验证码字符串
验证码通常由数字、字母或组合而成,长度一般为4-6位,使用以下代码生成随机字符串:
function generateRandomCode($length = 4) {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= $chars[rand(0, strlen($chars) - 1)];
}
return $code;
}
$code = generateRandomCode(4);
使用GD库绘制验证码图像
创建画布
$imageWidth = 120; $imageHeight = 40; $image = imagecreatetruecolor($imageWidth, $imageHeight);
定义颜色
$backgroundColor = imagecolorallocate($image, 255, 255, 255); // 白色背景 $textColor = imagecolorallocate($image, 0, 0, 0); // 黑色文字 $noiseColor = imagecolorallocate($image, 150, 150, 150); // 干扰元素颜色
填充背景
imagefill($image, 0, 0, $backgroundColor);
添加干扰线
for ($i = 0; $i < 5; $i++) {
imageline($image, rand(0, $imageWidth), rand(0, $imageHeight),
rand(0, $imageWidth), rand(0, $imageHeight), $noiseColor);
}
添加干扰点
for ($i = 0; $i < 50; $i++) {
imagesetpixel($image, rand(0, $imageWidth), rand(0, $imageHeight), $noiseColor);
}
输出验证码文字
$fontFile = 'arial.ttf'; // 确保服务器有该字体文件,或使用默认字体
$fontSize = 20;
$x = 20;
$y = 30;
for ($i = 0; $i < strlen($code); $i++) {
$angle = rand(-10, 10); // 随机倾斜角度
imagettftext($image, $fontSize, $angle, $x, $y, $textColor, $fontFile, $code[$i]);
$x += 25; // 调整字符间距
}
输出图像并释放资源
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
Session存储验证码值
在生成图像前,将验证码字符串存入Session:

session_start(); $_SESSION['captcha_code'] = $code;
完整验证码生成示例代码
<?php
session_start();
function generateCaptcha($length = 4) {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= $chars[rand(0, strlen($chars) - 1)];
}
return $code;
}
$imageWidth = 120;
$imageHeight = 40;
$image = imagecreatetruecolor($imageWidth, $imageHeight);
$backgroundColor = imagecolorallocate($image, 255, 255, 255);
$textColor = imagecolorallocate($image, 0, 0, 0);
$noiseColor = imagecolorallocate($image, 150, 150, 150);
imagefill($image, 0, 0, $backgroundColor);
for ($i = 0; $i < 5; $i++) {
imageline($image, rand(0, $imageWidth), rand(0, $imageHeight),
rand(0, $imageWidth), rand(0, $imageHeight), $noiseColor);
}
for ($i = 0; $i < 50; $i++) {
imagesetpixel($image, rand(0, $imageWidth), rand(0, $imageHeight), $noiseColor);
}
$code = generateCaptcha(4);
$_SESSION['captcha_code'] = $code;
$fontFile = 'arial.ttf';
$fontSize = 20;
$x = 20;
$y = 30;
for ($i = 0; $i < strlen($code); $i++) {
$angle = rand(-10, 10);
imagettftext($image, $fontSize, $angle, $x, $y, $textColor, $fontFile, $code[$i]);
$x += 25;
}
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
前端表单与后端验证
前端表单(HTML)
<form action="verify.php" method="post">
<img src="captcha.php" onclick="this.src='captcha.php?'+Math.random()" alt="验证码">
<input type="text" name="captcha_input" placeholder="请输入验证码">
<button type="submit">提交</button>
</form>
点击图片刷新验证码通过Math.random()实现URL参数变化,避免浏览器缓存。
后端验证(PHP)
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$userInput = $_POST['captcha_input'];
if (isset($_SESSION['captcha_code']) && strtolower($userInput) == strtolower($_SESSION['captcha_code'])) {
echo "验证成功!";
} else {
echo "验证码错误!";
}
unset($_SESSION['captcha_code']); // 验证后清除Session
}
?>
验证码增强技巧
- 字符变形:通过
imagettftext()的angle参数使字符倾斜,增加机器识别难度。 - 背景干扰:添加随机曲线、噪点或复杂背景图案。
- 字体选择:使用手写风格或艺术字体,避免标准字体。
- 时间限制:设置Session有效期,如30秒后验证码失效。
常见问题与解决方案
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 验证码图像无法显示 | GD库未启用或路径错误 | 检查php.ini中GD扩展,确认字体文件路径 |
| 验证码始终提示错误 | Session未开启或大小写敏感 | 确保调用session_start(),使用strtolower()统一大小写 |
相关问答FAQs
Q1:为什么验证码不区分大小写,但有时仍会验证失败?
A1:可能是Session未正确传递或浏览器缓存问题,建议在生成验证码时统一转换为小写存储(如$_SESSION['captcha_code'] = strtolower($code)),验证时也统一转换大小写比对,并确保表单提交时Session有效。
Q2:如何实现点击刷新验证码功能?
A2:在前端JavaScript中为验证码图片绑定点击事件,动态修改src属性添加随机参数(如Math.random())以绕过浏览器缓存,示例代码:
document.getElementById('captcha-img').onclick = function() {
this.src = 'captcha.php?' + Math.random();
}; 