今天分享一个生成验证码的工具kaptcha 。
Kaptcha 是 Google 开发的一个简单实用的验证码生成库,基于 javax.imageio 实现,配置灵活,易于集成到 Spring/Spring Boot 项目中。
maven项目中依赖
<!-- Maven 依赖 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
springboot中集成:
首先需要定义一个DefaultKaptcha的bean,用于生成验证码的图片和文字配置。以下是两个经典的案例(实际应用中可以根据需要设置纯数字或者算式,我们项目中只是生成的纯数字比较简单,我们是生成之后输出前端,然后存入redis中生成uuid做为验证批次号。验证时候前端传回来用户输的和uuid在redis中进行匹配,这个比较简单)下面直接上代码
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha defaultKaptcha() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 图片样式配置
properties.setProperty("kaptcha.border", "yes"); // 有边框
properties.setProperty("kaptcha.border.color", "105,179,90"); // 边框颜色
properties.setProperty("kaptcha.image.width", "160"); // 宽度
properties.setProperty("kaptcha.image.height", "60"); // 高度
// 文本配置
properties.setProperty("kaptcha.textproducer.font.color", "blue"); // 字体颜色
properties.setProperty("kaptcha.textproducer.font.size", "35"); // 字体大小
properties.setProperty("kaptcha.textproducer.char.length", "4"); // 字符个数
properties.setProperty("kaptcha.textproducer.char.space", "3"); // 字符间距
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier"); // 字体
// 干扰配置
properties.setProperty("kaptcha.noise.color", "red"); // 干扰线颜色
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise"); // 干扰实现
// 背景配置
properties.setProperty("kaptcha.background.clear.from", "white"); // 背景渐变开始
properties.setProperty("kaptcha.background.clear.to", "white"); // 背景渐变结束
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
// 数学算式验证码配置(如:1+2=?)
@Bean
public DefaultKaptcha mathKaptcha() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.image.width", "160");
properties.setProperty("kaptcha.image.height", "60");
properties.setProperty("kaptcha.textproducer.font.size", "35");
// 使用数学算式文本生成器
properties.setProperty("kaptcha.textproducer.impl",
"com.xxx.MathTextCreator"); // 自定义类
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
controller实现
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
@Autowired
private DefaultKaptcha defaultKaptcha;
/**
* 生成验证码图片
*/
@GetMapping("/image")
public void getCaptcha(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// 设置响应头
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control",
"no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
// 生成验证码文本
String captchaText = defaultKaptcha.createText();
// 存储到Session(推荐使用Redis存储分布式应用)
request.getSession().setAttribute("CAPTCHA_SESSION_KEY", captchaText);
// 可选:存储到Redis(分布式场景)或者生成UUID传给前端
String sessionId = request.getSession().getId();
redisTemplate.opsForValue().set(
"captcha:" + sessionId,
captchaText,
5, TimeUnit.MINUTES
);
// 生成图片并写出
BufferedImage image = defaultKaptcha.createImage(captchaText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
/**
* 验证码验证
*/
@PostMapping("/verify")
public ApiResult verifyCaptcha(@RequestParam String code,
HttpServletRequest request) {
// 从Session获取验证码
String sessionCaptcha = (String) request.getSession()
.getAttribute("CAPTCHA_SESSION_KEY");
// 从Redis获取(分布式场景)
String sessionId = request.getSession().getId();
String redisCaptcha = redisTemplate.opsForValue()
.get("captcha:" + sessionId);
if (StringUtils.isBlank(sessionCaptcha)) {
return ApiResult.error("验证码已失效");
}
if (StringUtils.isBlank(code)) {
return ApiResult.error("请输入验证码");
}
if (!sessionCaptcha.equalsIgnoreCase(code.trim())) {
return ApiResult.error("验证码错误");
}
// 验证成功后清除验证码
request.getSession().removeAttribute("CAPTCHA_SESSION_KEY");
redisTemplate.delete("captcha:" + sessionId);
//处理后续登陆操作
return ApiResult.success("验证码正确");
}
}