在PHP开发中,将验证码和表单验证联动是防止恶意提交、暴力破解的常用方案,核心思路是生成验证码后把内容存入session,表单提交时对比用户输入和session中存储的验证码值,一致则通过校验。

一、验证码生成实现
首先我们需要生成随机的验证码字符串,并将内容保存到session中,同时输出验证码图片给前端展示。以下是生成验证码的PHP代码:
<?php
// 开启session
session_start();
// 生成4位随机验证码,包含数字和字母
$code = '';
$charList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charLength = strlen($charList);
for ($i = 0; $i < 4; $i++) {
$code .= $charList[rand(0, $charLength - 1)];
}
// 将验证码存入session
$_SESSION['captcha_code'] = $code;
// 创建验证码图片
$width = 120;
$height = 40;
$image = imagecreatetruecolor($width, $height);
// 设置背景色为浅灰色
$bgColor = imagecolorallocate($image, 240, 240, 240);
imagefill($image, 0, 0, $bgColor);
// 设置文字颜色为黑色
$textColor = imagecolorallocate($image, 0, 0, 0);
// 写入验证码文字
imagestring($image, 5, 30, 10, $code, $textColor);
// 输出图片并销毁资源
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
二、前端表单页面实现
前端需要展示表单、验证码图片,同时提供刷新验证码的功能,以下是完整的HTML表单代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>PHP验证码表单验证</title>
</head>
<body>
<h3>用户登录</h3>
<form method="post" action="check.php">
<p>
用户名:<input type="text" name="username" required>
</p>
<p>
密码:<input type="password" name="password" required>
</p>
<p>
验证码:<input type="text" name="captcha" required>
<img src="captcha.php" onclick="this.src='captcha.php?'+Math.random()" alt="验证码">
<em>点击图片刷新验证码</em>
</p>
<p>
<input type="submit" value="提交">
</p>
</form>
</body>
</html>
这里验证码图片的src指向我们之前写的验证码生成脚本captcha.php,点击图片时通过拼接随机参数刷新验证码,避免浏览器缓存导致验证码不更新。
三、表单提交后的验证逻辑
表单提交到check.php后,我们需要先校验验证码,再处理其他表单数据,以下是验证逻辑的代码:
<?php
session_start();
// 判断是否是POST提交
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo '非法请求';
exit;
}
// 获取表单提交的验证码
$inputCaptcha = trim($_POST['captcha'] ?? '');
// 获取session中存储的验证码,转小写统一对比
$sessionCaptcha = strtolower($_SESSION['captcha_code'] ?? '');
$inputCaptchaLower = strtolower($inputCaptcha);
// 验证码校验
if (empty($inputCaptcha)) {
echo '请输入验证码';
exit;
}
if (empty($sessionCaptcha)) {
echo '验证码已过期,请刷新重试';
exit;
}
if ($inputCaptchaLower !== $sessionCaptcha) {
echo '验证码错误';
exit;
}
// 验证码校验通过后,清除session中的验证码,防止重复使用
unset($_SESSION['captcha_code']);
// 后续处理其他表单数据,比如验证用户名密码
$username = trim($_POST['username'] ?? '');
$password = trim($_POST['password'] ?? '');
// 这里可以添加用户名密码的校验逻辑,比如查询数据库
echo '表单验证通过,用户名:' . htmlspecialchars($username);
?>
四、注意事项
- 一定要在使用session之前调用
session_start()函数,否则无法读取和存储session数据。 - 验证码校验通过后要立即清除session中的验证码,避免同一个验证码被重复使用,导致安全问题。
- 对比验证码时建议统一转成小写或者大写,避免用户输入大小写不一致导致验证失败。
- 生产环境中可以给验证码图片添加干扰线、噪点,提升验证码的识别难度,增强安全性。
五、常见问题排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 验证码一直提示错误 | session没有正确开启,或者验证码生成和校验的session键名不一致 | 检查两个文件的session_start()调用,确保存储和读取的键名都是captcha_code |
| 验证码图片不显示 | 验证码脚本有输出内容,或者header之前有空白输出 | 确保captcha.php中header调用之前没有任何输出,包括空格和换行 |
| 点击验证码图片不刷新 | 浏览器缓存了验证码图片 | 给图片src拼接随机参数,比如Math.random()生成的时间戳 |