本文目录导读:

我来详细介绍PHP实现验证码功能的几种常见方法。
GD库图形验证码
基本验证码生成
<?php
// captcha.php
session_start();
// 生成随机验证码
$length = 4;
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 去除容易混淆的字符
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= $chars[rand(0, strlen($chars) - 1)];
}
// 存储验证码到Session
$_SESSION['captcha'] = $code;
// 创建图片
$width = 120;
$height = 40;
$image = imagecreatetruecolor($width, $height);
// 设置颜色
$bgColor = imagecolorallocate($image, 255, 255, 255);
$textColor = imagecolorallocate($image, 0, 0, 0);
$lineColor = imagecolorallocate($image, 200, 200, 200);
$pixelColor = imagecolorallocate($image, 150, 150, 150);
// 填充背景
imagefill($image, 0, 0, $bgColor);
// 添加干扰线
for ($i = 0; $i < 5; $i++) {
imageline($image, rand(0, $width), rand(0, $height),
rand(0, $width), rand(0, $height), $lineColor);
}
// 添加干扰点
for ($i = 0; $i < 100; $i++) {
imagesetpixel($image, rand(0, $width), rand(0, $height), $pixelColor);
}
// 写入文字
$fontSize = 20;
$x = 20;
for ($i = 0; $i < $length; $i++) {
$angle = rand(-30, 30);
$y = rand(25, 35);
imagettftext($image, $fontSize, $angle, $x, $y, $textColor,
'path/to/font.ttf', $code[$i]);
$x += 20;
}
// 输出图片
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
HTML显示验证码
<!-- login.html -->
<!DOCTYPE html>
<html>
<head>登录</title>
</head>
<body>
<form method="post" action="login.php">
<!-- 其他表单字段 -->
<div>
<input type="text" name="captcha" placeholder="验证码" required>
<img src="captcha.php" id="captchaImage" onclick="refreshCaptcha()">
<a href="javascript:void(0)" onclick="refreshCaptcha()">换一张</a>
</div>
<button type="submit">登录</button>
</form>
<script>
function refreshCaptcha() {
document.getElementById('captchaImage').src = 'captcha.php?' + Math.random();
}
</script>
</body>
</html>
验证码校验
<?php
// login.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$captcha = strtoupper($_POST['captcha']);
if ($captcha === $_SESSION['captcha']) {
// 验证成功
echo "验证码正确,登录成功!";
// 清除验证码(防止重复使用)
unset($_SESSION['captcha']);
} else {
echo "验证码错误,请重新输入!";
}
}
?>
使用第三方库
Gregwar/Captcha库
composer require gregwar/captcha
<?php
use Gregwar\Captcha\CaptchaBuilder;
session_start();
// 创建验证码
$builder = new CaptchaBuilder;
$builder->build();
// 存储验证码
$_SESSION['phrase'] = $builder->getPhrase();
// 输出图片
header('Content-Type: image/jpeg');
$builder->output();
?>
mewebstudio/captcha库(Laravel常用)
// 安装
composer require mewebstudio/captcha
// 生成验证码
Captcha::create(); // 返回图片信息
// 验证
if (Captcha::check($input)) {
// 验证通过
}
短信/邮箱验证码
发送验证码接口
<?php
// send_code.php
session_start();
function generateCode($length = 6) {
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= rand(0, 9);
}
return $code;
}
// 生成验证码
$code = generateCode();
// 存储验证码和过期时间
$_SESSION['sms_code'] = $code;
$_SESSION['sms_code_time'] = time();
// 发送短信(示例使用阿里云短信)
function sendSMS($phone, $code) {
// 对接短信服务商API
// 阿里云、腾讯云、七牛云等
}
// 发送邮箱验证码
function sendEmail($email, $code) {
// 使用PHPMailer等库发送邮件
}
// 根据场景调用
$type = $_POST['type']; // sms或email
$target = $_POST['target']; // 手机号或邮箱
if ($type === 'sms') {
sendSMS($target, $code);
echo json_encode(['status' => 'success', 'message' => '验证码已发送']);
} elseif ($type === 'email') {
sendEmail($target, $code);
echo json_encode(['status' => 'success', 'message' => '验证码已发送']);
}
?>
验证码校验接口
<?php
// verify_code.php
session_start();
$inputCode = $_POST['code'];
$storedCode = $_SESSION['sms_code'];
$storedTime = $_SESSION['sms_code_time'];
// 检查验证码是否匹配
if ($inputCode === $storedCode) {
// 检查是否过期(例如5分钟)
if (time() - $storedTime <= 300) {
echo json_encode(['status' => 'success', 'message' => '验证成功']);
// 清除验证码
unset($_SESSION['sms_code']);
unset($_SESSION['sms_code_time']);
} else {
echo json_encode(['status' => 'error', 'message' => '验证码已过期']);
}
} else {
echo json_encode(['status' => 'error', 'message' => '验证码错误']);
}
?>
高级功能实现
验证码频率限制
<?php
session_start();
function checkRateLimit($key, $maxAttempts = 5, $timeWindow = 300) {
$now = time();
$attempts = $_SESSION[$key] ?? [];
// 清理过期记录
$attempts = array_filter($attempts, function($time) use ($now) {
return $now - $time <= $timeWindow;
});
if (count($attempts) >= $maxAttempts) {
return false; // 超过限制
}
$attempts[] = $now;
$_SESSION[$key] = $attempts;
return true;
}
// 使用
if (!checkRateLimit('captcha_attempts')) {
die('请求过于频繁,请稍后再试');
}
?>
多次输入错误后锁定
<?php
session_start();
function checkLoginAttempts($username) {
$key = 'login_attempts_' . $username;
$attempts = $_SESSION[$key] ?? ['count' => 0, 'lock_time' => 0];
if ($attempts['lock_time'] > time()) {
return false; // 账户被锁定
}
if ($attempts['count'] >= 3) {
$attempts['lock_time'] = time() + 300; // 锁定5分钟
$_SESSION[$key] = $attempts;
return false;
}
return true;
}
function incrementAttempts($username) {
$key = 'login_attempts_' . $username;
$attempts = $_SESSION[$key] ?? ['count' => 0, 'lock_time' => 0];
$attempts['count']++;
$_SESSION[$key] = $attempts;
}
function resetAttempts($username) {
$key = 'login_attempts_' . $username;
unset($_SESSION[$key]);
}
?>
安全建议
- 使用HTTPS:防止验证码在传输过程中被截获
- 验证码时效性:设置合理的过期时间(通常5-10分钟)
- 一次性使用:验证成功后立即清除
- 图形干扰:添加噪点、干扰线、扭曲等
- 大小写处理:通常不区分大小写
- 频率限制:防止暴力破解
- 避免使用简单字符:如0和O、1和I等
完整示例代码
<?php
// 完整的验证码类
class Captcha {
private $width = 120;
private $height = 40;
private $length = 4;
private $characters = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
public function generate() {
session_start();
// 生成验证码
$code = '';
for ($i = 0; $i < $this->length; $i++) {
$code .= $this->characters[rand(0, strlen($this->characters) - 1)];
}
$_SESSION['captcha'] = $code;
$_SESSION['captcha_time'] = time();
return $code;
}
public function output() {
$code = $this->generate();
$image = imagecreatetruecolor($this->width, $this->height);
// 设置颜色
$bgColor = imagecolorallocate($image, 255, 255, 255);
$textColor = imagecolorallocate($image, 0, 0, 0);
$lineColor = imagecolorallocate($image, 200, 200, 200);
imagefill($image, 0, 0, $bgColor);
// 添加干扰线
for ($i = 0; $i < 5; $i++) {
imageline($image, rand(0, $this->width), rand(0, $this->height),
rand(0, $this->width), rand(0, $this->height), $lineColor);
}
// 写入文字
$fontSize = 20;
$x = 20;
for ($i = 0; $i < $this->length; $i++) {
imagestring($image, $fontSize, $x, rand(10, 20), $code[$i], $textColor);
$x += 20;
}
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
}
public function verify($input, $caseInsensitive = true) {
session_start();
if (!isset($_SESSION['captcha'])) {
return false;
}
// 检查是否过期(5分钟)
if (time() - $_SESSION['captcha_time'] > 300) {
unset($_SESSION['captcha']);
return false;
}
$stored = $_SESSION['captcha'];
if ($caseInsensitive) {
$input = strtoupper($input);
}
$result = $input === $stored;
// 清除验证码
unset($_SESSION['captcha']);
unset($_SESSION['captcha_time']);
return $result;
}
}
// 使用示例
$captcha = new Captcha();
$captcha->output(); // 生成验证码图片
// 验证
if ($captcha->verify($_POST['captcha'])) {
echo "验证成功";
} else {
echo "验证失败";
}
?>
这些方法涵盖了从基础的图形验证码到高级的短信/邮箱验证码实现,你可以根据项目需求选择合适的方案。