PHP验证码是网站常用的安全验证手段,通过生成包含随机字符的图片,要求用户输入图片中的内容,以此区分用户是真人还是机器程序,有效防止恶意批量注册、暴力破解密码等行为。

PHP验证码的生成原理
PHP生成验证码的核心流程可以分为四个步骤:
- 生成随机字符串:从预设的字符集中随机选取若干字符,组成验证码内容
- 创建图像画布:使用GD库函数创建空白图像,设置背景颜色
- 绘制验证码内容:将随机字符串写入图像,同时添加干扰线、噪点等元素,防止机器识别
- 存储验证码内容:将生成的随机字符串存入session,方便后续验证用户输入
环境准备
首先需要确保PHP环境已经安装并启用了GD库,可以通过phpinfo()函数查看GD库是否开启。如果没有开启,需要在php.ini配置文件中取消extension=gd的注释,然后重启PHP服务。
完整代码实现
1. 生成验证码图像
创建captcha.php文件,用于生成验证码图片:
<?php
session_start();
// 设置验证码字符集,去除容易混淆的字符如0、o、1、l
$charSet = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
// 验证码长度
$codeLen = 4;
// 生成随机验证码字符串
$captchaCode = '';
for ($i = 0; $i < $codeLen; $i++) {
$captchaCode .= $charSet[mt_rand(0, strlen($charSet) - 1)];
}
// 将验证码存入session
$_SESSION['captcha_code'] = $captchaCode;
// 创建图像画布,宽120px,高40px
$width = 120;
$height = 40;
$image = imagecreatetruecolor($width, $height);
// 设置背景颜色为浅灰色
$bgColor = imagecolorallocate($image, 240, 240, 240);
imagefill($image, 0, 0, $bgColor);
// 添加干扰线,随机生成6条
for ($i = 0; $i < 6; $i++) {
$lineColor = imagecolorallocate($image, mt_rand(100, 200), mt_rand(100, 200), mt_rand(100, 200));
imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $lineColor);
}
// 添加干扰点,随机生成100个
for ($i = 0; $i < 100; $i++) {
$pixelColor = imagecolorallocate($image, mt_rand(50, 150), mt_rand(50, 150), mt_rand(50, 150));
imagesetpixel($image, mt_rand(0, $width), mt_rand(0, $height), $pixelColor);
}
// 设置验证码字符颜色
$textColor = imagecolorallocate($image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
// 每个字符的宽度
$charWidth = $width / $codeLen;
// 逐个绘制验证码字符,每个字符随机偏移角度
for ($i = 0; $i < $codeLen; $i++) {
$char = $captchaCode[$i];
$angle = mt_rand(-30, 30);
$x = $i * $charWidth + mt_rand(5, 10);
$y = mt_rand($height / 2, $height - 5);
imagettftext($image, 18, $angle, $x, $y, $textColor, 'C:/Windows/Fonts/arial.ttf', $char);
}
// 设置响应头为图像类型
header('Content-Type: image/png');
// 输出图像
imagepng($image);
// 销毁图像资源
imagedestroy($image);
?>
2. 前端调用验证码
在需要展示验证码的页面中,通过<img>标签调用captcha.php生成图片,同时提供刷新验证码的功能:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>验证码测试页面</title>
</head>
<body>
<form action="check.php" method="post">
<label>验证码:</label>
<input type="text" name="captcha_input" required>
<img src="captcha.php" onclick="this.src='captcha.php?'+Math.random()" alt="验证码" style="cursor:pointer;">
<span>点击图片刷新验证码</span>
<br><br>
<input type="submit" value="提交验证">
</form>
</body>
</html>
3. 验证用户输入
创建check.php文件,用于验证用户输入的验证码是否正确:
<?php
session_start();
// 获取用户输入的验证码
$inputCode = isset($_POST['captcha_input']) ? strtolower(trim($_POST['captcha_input'])) : '';
// 获取session中存储的验证码,转为小写
$sessionCode = isset($_SESSION['captcha_code']) ? strtolower($_SESSION['captcha_code']) : '';
if (empty($inputCode) || empty($sessionCode)) {
echo '验证码不能为空';
} elseif ($inputCode === $sessionCode) {
echo '验证码验证通过';
// 验证通过后销毁session中的验证码,防止重复使用
unset($_SESSION['captcha_code']);
} else {
echo '验证码错误,请重新输入';
}
?>
注意事项
- 验证码字符集尽量不要包含容易混淆的字符,比如数字0和字母o,数字1和字母l,减少用户识别错误
- 干扰线和噪点的颜色不要和字符颜色差异过大,既要保证干扰效果,也要让用户能够清晰识别字符
- 验证通过后要及时销毁session中的验证码,避免同一个验证码被重复使用,带来安全风险
- 如果需要更高的安全性,可以增加验证码的过期时间,比如生成时记录时间,验证时检查是否超过有效期