『博客开发日记-后台』之生成图形验证码接口的实现

本文最后更新于 2026年3月27日 下午

生成图形验证码接口的实现


生成图形验证码接口的需求

图形验证码的存在,主要为了防止有自动化机器人持续进行登录导致接口压力增大

通过验证码生成工具来生成图形验证码

验证码生成之后存入redis(2分钟)

代码

先创建图形验证码生成工具类,这个主要负责生成随机的验证码并将其转换为图片形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 验证码工具类
*/
public class CaptchaUtil {

private static final String CODES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final int WIDTH = 120;
private static final int HEIGHT = 40;
private static final int CODE_LENGTH = 4;
private static final Random RANDOM = new Random();

/**
* 生成验证码文本
*/
public static String generateCode() {
StringBuilder code = new StringBuilder();
for (int i = 0; i < CODE_LENGTH; i++) {
code.append(CODES.charAt(RANDOM.nextInt(CODES.length())));
}
return code.toString();
}

/**
* 生成验证码图片并转为Base64
*/
public static String generateImageBase64(String code) throws IOException {
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();

// 设置背景色
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);

// 设置字体
g.setFont(new Font("Arial", Font.BOLD, 32));

// 绘制验证码
for (int i = 0; i < code.length(); i++) {
// 随机颜色
g.setColor(new Color(RANDOM.nextInt(150), RANDOM.nextInt(150), RANDOM.nextInt(150)));
// 随机位置和角度
int x = 20 + i * 25;
int y = 28 + RANDOM.nextInt(8);
g.drawString(String.valueOf(code.charAt(i)), x, y);
}

// 绘制干扰线
for (int i = 0; i < 5; i++) {
g.setColor(new Color(RANDOM.nextInt(200), RANDOM.nextInt(200), RANDOM.nextInt(200)));
int x1 = RANDOM.nextInt(WIDTH);
int y1 = RANDOM.nextInt(HEIGHT);
int x2 = RANDOM.nextInt(WIDTH);
int y2 = RANDOM.nextInt(HEIGHT);
g.drawLine(x1, y1, x2, y2);
}

// 绘制噪点
for (int i = 0; i < 50; i++) {
g.setColor(new Color(RANDOM.nextInt(255), RANDOM.nextInt(255), RANDOM.nextInt(255)));
g.fillRect(RANDOM.nextInt(WIDTH), RANDOM.nextInt(HEIGHT), 1, 1);
}

g.dispose();

// 转换为Base64
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
return "data:image/png;base64," + base64;
}
}

然后创建与验证码相关的接口,这里不再演示

然后实现服务功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//获取图形验证码
@Override
public ResponseResult captcha(UserLoginDto dto)
{
try {
// 生成验证码ID
String captchaId = UUID.randomUUID().toString();

// 生成验证码文本
String code = CaptchaUtil.generateCode();

// 生成验证码图片Base64
String base64Img = CaptchaUtil.generateImageBase64(code);

// 将验证码存入Redis,有效期2分钟
redisCache.setCacheObject("captcha:" + captchaId, code, 2, java.util.concurrent.TimeUnit.MINUTES);

// 在控制台输出验证码(方便开发调试)
System.out.println("========================================");
System.out.println("验证码ID: " + captchaId);
System.out.println("验证码内容: " + code);
System.out.println("========================================");

// 构建响应数据
Map<String, String> result = new HashMap<>();
result.put("captchaId", captchaId);
result.put("captchaBase64", base64Img);

return ResponseResult.okResult(result);
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
}
}

最后就是给这个接口放行


测试图形验证码接口


测试登录接口




PS:该系列只做为作者学习开发项目做的笔记用

不一定符合读者来学习,仅供参考


预告

后续会记录博客的开发过程

每次学习会做一份笔记来进行发表

“一花一世界,一叶一菩提”


版权所有 © 2026 云梦泽
欢迎访问我的个人网站:https://hgt12.github.io/


『博客开发日记-后台』之生成图形验证码接口的实现
http://example.com/2026/03/27/『博客开发日记-后台』之生成图形验证码接口的实现/
作者
云梦泽
发布于
2026年3月27日
更新于
2026年3月27日
许可协议