SpringBoot3 集成 Kaptcha 图形验证码 + Redis 缓存
·
前言
图形验证码是后端开发中最常用的安全校验手段,广泛应用于登录、注册、短信发送等场景。本文基于 SpringBoot3.2.5 快速集成 Kaptcha 生成图形验证码,并将验证码存入 Redis 实现30 秒自动过期,代码简洁、可直接复制运行,完美适配 SpringBoot3 新版本。
一、技术栈
十、总结
本文实现了 SpringBoot3 集成 Kaptcha 图形验证码 + Redis 缓存的完整方案,代码简洁、无冗余、可直接上线使用。核心流程:生成验证码 → Redis 缓存 → 图片输出,是后端登录校验模块的标准实现方案。
- SpringBoot 3.2.5
- Kaptcha 2.3.2(图形验证码生成)
- Redis(验证码缓存 + 自动过期)
- Java 17
- Maven
-
二、Maven 依赖(pom.xml)
引入 Web、Redis、Kaptcha 核心依赖,SpringBoot3 自动管理版本:
-
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> </parent> <groupId>com.demo</groupId> <artifactId>captcha-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>17</java.version> </properties> <dependencies> <!-- Web 核心 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Redis 缓存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- Kaptcha 验证码 --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>三、配置文件(application.yml)
配置 Redis 连接信息,简洁无冗余:
-
server: port: 8080 spring: # Redis 配置 redis: host: 127.0.0.1 port: 6379 password: database: 0 timeout: 10000四、Kaptcha 配置类(验证码样式)
自定义验证码长度、字体、干扰线、尺寸:
package com.demo.config; import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; @Configuration public class KaptchaConfig { @Bean public Producer captchaProducer() { Properties properties = new Properties(); // 验证码图片宽度 properties.setProperty("kaptcha.image.width", "120"); // 验证码图片高度 properties.setProperty("kaptcha.image.height", "40"); // 字体大小 properties.setProperty("kaptcha.textproducer.font.size", "30"); // 验证码长度 properties.setProperty("kaptcha.textproducer.char.length", "4"); // 字体颜色 properties.setProperty("kaptcha.textproducer.font.color", "black"); // 字符范围 properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); return defaultKaptcha; } }五、Redis 配置类(序列化)
解决 Redis 存储乱码问题:
-
package com.demo.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 序列化配置 StringRedisSerializer stringSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); jacksonSerializer.setObjectMapper(om); template.setKeySerializer(stringSerializer); template.setValueSerializer(jacksonSerializer); template.afterPropertiesSet(); return template; } }六、工具类(IP 获取 + MD5 加密)
生成唯一的验证码 Key,防止重复:
-
package com.demo.utils; import jakarta.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class CommonUtil { /** * 获取客户端IP */ public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } /** * MD5加密生成唯一Key */ public static String md5(String str) { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(str.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(b & 0xff); if (hex.length() == 1) sb.append("0"); sb.append(hex); } return sb.toString(); } catch (NoSuchAlgorithmException e) { return null; } } }七、验证码 Controller(核心接口)
生成验证码 → 存入 Redis(30 秒过期) → 返回图片流:
-
package com.demo.controller; import com.demo.utils.CommonUtil; import com.google.code.kaptcha.Producer; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/api/auth") public class CaptchaController { @Autowired private Producer captchaProducer; @Autowired private RedisTemplate<String, Object> redisTemplate; /** * 获取图形验证码 */ @GetMapping("/captcha") public void getCaptcha(HttpServletRequest request, HttpServletResponse response) { try { // 1. 生成验证码文本 String captchaText = captchaProducer.createText(); // 2. 生成唯一Key(IP+浏览器标识) String key = "captcha:" + CommonUtil.md5( CommonUtil.getIpAddr(request) + request.getHeader("User-Agent") ); // 3. 存入Redis 30秒过期 redisTemplate.opsForValue().set(key, captchaText, 30, TimeUnit.SECONDS); // 4. 生成图片 BufferedImage image = captchaProducer.createImage(captchaText); // 5. 设置响应头 response.setContentType("image/png"); response.setHeader("Cache-Control", "no-cache"); // 6. 输出图片 ImageIO.write(image, "png", response.getOutputStream()); response.getOutputStream().flush(); } catch (IOException e) { e.printStackTrace(); } } }八、启动测试
- 启动本地 Redis 服务
- 启动 SpringBoot 项目
- 浏览器访问地址:
-
http://localhost:8080/api/auth/captcha -
九、功能说明
- 验证码生成:Kaptcha 自动生成 4 位字母 + 数字组合验证码
- 缓存策略:基于用户 IP + 浏览器标识生成唯一 Key,存入 Redis
- 过期时间:30 秒自动失效,保证安全性
- SpringBoot3 适配:使用
jakarta.servlet包,无版本兼容问题
更多推荐


所有评论(0)