本文详细讲解 SpringBoot 项目中图形验证码的两种实现方案,包括手写自定义验证码工具类和基于 Hutool 工具库快速集成线段、圆形、扭曲、GIF 四种验证码,附带完整代码示例与接口测试步骤,帮助开发者解决登录、注册等场景的人机验证需求。
一、为什么需要图形验证码?
在登录、注册、密码重置等用户交互场景中,图形验证码是防御恶意脚本、暴力破解的重要手段。它通过将随机字符与干扰元素结合,确保操作由真实用户完成,而非自动化程序。
传统实现方式有两种:一是手动编写验证码生成逻辑,二是使用成熟工具库快速集成。下面分别讲解这两种方案的具体操作,你可以根据项目需求选择合适的方式。
二、方案一:手写自定义验证码工具类
如果需要高度定制验证码样式(如特定字体、干扰线密度),可以手动开发工具类。以下是完整实现步骤。
2.1 新建验证码工具类
在 SpringBoot 项目的 util 包下创建 Code 类,核心逻辑包括生成随机字符、绘制干扰线、输出图片到响应流,并将验证码存入 Session 用于后续验证。
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Code {
// 存储验证码到 Session 的 key
public static final String RANDOMCODEKEY = "ValidateCode";
// 随机数生成器
private final Random random = new Random();
// 验证码字符库(数字 + 大写字母)private final String randomString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 验证码图片宽高与干扰线配置
private int width = 80;
private int height = 26;
private int lineSize = 40;
private int stringNum = 4;
/**
* 获取验证码字体(固定为 Fixedsys,大小 18)*/
private Font getFont() {return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
}
/**
* 生成随机颜色(避免颜色过深或过浅)*/
private Color getRandColor(int fc, int bc) {if (fc > 255) fc = 255;
if (bc > 255) bc = 255;
int r = fc + random.nextInt(bc - fc - 16);
int g = fc + random.nextInt(bc - fc - 14);
int b = fc + random.nextInt(bc - fc - 18);
return new Color(r, g, b);
}
/**
* 绘制干扰线(随机位置、随机长度)*/
private void drawLine(Graphics g) {int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl);
}
/**
* 绘制随机字符(随机颜色、轻微偏移)*/
private String drawString(Graphics g, String randomStr, int i) {g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
String charStr = String.valueOf(randomString.charAt(random.nextInt(randomString.length())));
randomStr += charStr;
// 字符位置轻微偏移,增加识别难度
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(charStr, 13 * i, 16);
return randomStr;
}
/**
* 核心方法:生成验证码并输出到响应流
*/
public void getValidateCode(HttpServletRequest request, HttpServletResponse response) {HttpSession session = request.getSession();
// 1. 创建图片缓冲区
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
// 2. 绘制图片背景
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
g.setColor(getRandColor(110, 133));
// 3. 绘制干扰线
for (int i = 0; i <= lineSize; i++) {drawLine(g);
}
// 4. 绘制验证码字符
String randomStr = "";
for (int i = 1; i <= stringNum; i++) {randomStr = drawString(g, randomStr, i);
}
// 5. 存储验证码到 Session(覆盖旧值)session.removeAttribute(RANDOMCODEKEY);
session.setAttribute(RANDOMCODEKEY, randomStr);
// 6. 关闭资源并输出图片
g.dispose();
try {ImageIO.write(image, "JPEG", response.getOutputStream());
} catch (Exception e) {e.printStackTrace();
}
}
}
2.2 在 Controller 中调用工具类
创建CaptchaController,定义接口/checkCode2,设置响应格式为图片,并禁用浏览器缓存(避免验证码重复加载)。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
public class CaptchaController {
/**
* 自定义验证码接口
*/
@GetMapping("/checkCode2")
public void checkCode2(HttpServletRequest request, HttpServletResponse response) {
// 1. 设置响应格式为 JPEG 图片
response.setContentType("image/jpeg");
// 2. 禁用浏览器缓存(关键:避免验证码复用)response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
// 3. 调用工具类生成验证码
Code code = new Code();
code.getValidateCode(request, response);
}
}
三、方案二:使用 Hutool 快速集成验证码
Hutool 是 Java 生态中常用的工具库,其 hutool-captcha 模块已封装好四种验证码,无需重复开发,推荐项目中优先使用。
3.1 引入 Hutool 依赖
在 pom.xml 中添加依赖(Maven),如果是 Gradle 项目,可参考 Hutool 官网 调整配置。
<!-- 方式 1:仅引入图形验证码模块(轻量)-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.6</version>
</dependency>
<!-- 方式 2:引入 Hutool 所有模块(适合需其他工具类的场景)-->
<!--
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
-->
3.2 四种验证码实现示例
Hutool 提供LineCaptcha(线段干扰)、CircleCaptcha(圆形干扰)、ShearCaptcha(扭曲干扰)、GifCaptcha(动态 GIF),接口调用逻辑类似,仅需修改验证码创建方式。
3.2.1 线段干扰验证码(LineCaptcha)
最基础的验证码类型,通过线段干扰提高安全性。
继续阅读全文:SpringBoot 图形验证码实现教程:从自定义开发到 Hutool 工具类实战