pom文件中引入DefaultKaptcha的依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如
- 验证码的字体
- 验证码字体的大小
- 验证码字体的字体颜色
- 验证码内容的范围(数字,字母,中文汉字!)
- 验证码图片的大小,边框,边框粗细,边框颜色
- 验证码的干扰线
- 验证码的样式(鱼眼样式、3D、普通模糊、…)
CaptchaConfig类中配置验证码相关的参数(字符验证码)
若依的配置文件在这里
若依的验证码操作处理
提供了一个 getCode() 方法,用于生成验证码图片并将验证码信息保存到 Redis 缓存中。
首先判断是否启用了验证码功能,如果没有启用则直接返回一个 AjaxResult 对象,其中包含 captchaEnabled 字段(bool 类型),值为 false。
如果启用了验证码,则生成一个随机的 uuid 并将其作为验证码存储的 key,将验证码的值作为 value 存储到 Redis 缓存中,同时将验证码图片以 base64 格式返回给前端。
/**
* 验证码操作处理
*
* @author core
*/
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer; // 验证码生成器,用于生成字符验证码图片
//自动装配 Spring 框架的相关注解(例如 @RestController、@Resource、@Autowired),这些注解在程序启动时会被解析,在需要时自动创建对象并注入依赖。
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath; // 验证码生成器,用于生成数学计算验证码图片
@Autowired
private RedisCache redisCache; // Redis 缓存服务,用于保存验证码信息
@Autowired
private ISysConfigService configService; // 配置服务,用于获取是否启用验证码等信息
/**
* 生成验证码图片
* @param response HTTP 响应对象
* @throws IOException IO 异常
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success(); // 创建 AjaxResult 对象,用于封装返回到前端的数据
boolean captchaEnabled = configService.selectCaptchaEnabled(); // 获取是否启用验证码
ajax.put("captchaEnabled", captchaEnabled); // 将是否启用验证码的值保存到 AjaxResult 对象中,以返回到前端
if (!captchaEnabled) // 如果未启用验证码,直接返回 AjaxResult 对象
{
return ajax;
}
// 生成验证码信息
String uuid = IdUtils.simpleUUID(); // 随机生成 UUID 作为 Key
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; // 构造验证码 Key,用于在缓存中保存验证码信息
String capStr = null, code = null; // 验证码字符串和验证码值
BufferedImage image = null; // 验证码图片
// 生成验证码图片和验证码值
String captchaType = CoreConfig.getCaptchaType(); // 获取验证码类型,可选值有:"char" 和 "math"
if ("math".equals(captchaType)) // 如果验证码类型为数学计算类型
{
String capText = captchaProducerMath.createText(); // 生成一个包含数学计算公式的验证码字符串
// System.out.println(capText);
// 4-2=?@2
capStr = capText.substring(0, capText.lastIndexOf("@")); // 将计算公式截取出来
code = capText.substring(capText.lastIndexOf("@") + 1); // 将计算结果截取出来
image = captchaProducerMath.createImage(capStr);// 生成验证码图片
}
else if ("char".equals(captchaType))// 如果验证码类型为字符类型
{
capStr = code = captchaProducer.createText();// 生成纯字符验证码字符串,并将其作为验证码值和验证码字符串
image = captchaProducer.createImage(capStr); // 生成验证码图片
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); // 将验证码信息存储到缓存中,验证码 Key 为 verifyKey,验证码值为 code
// 转换验证码图片流,并以 base64 格式返回
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid); // 将 UUID 作为 'uuid' 键保存到 AjaxResult 中,以返回到前端
ajax.put("img", Base64.encode(os.toByteArray()));// 将验证码图片的 base64 编码保存到 'img' 键中,以返回到前端
return ajax;
}
}
前端页面利用Img标签的src属性,根据Base64编码格式数据获取验证码图片显示。
// 获取验证码方法
getCode() {
getCodeImg().then(res => {
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
});
},
<!-- 利用img标签,src属性根据Base64编码格式数据来获取验证码图。 -->
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div>
校验验证码
public void validateCaptcha(String username, String code, String uuid)
{
boolean captchaEnabled = configService.selectCaptchaEnabled(); // 获取是否启用验证码
if (captchaEnabled) { // 如果启用验证码
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); // 构建缓存中验证码的 key
String captcha = redisCache.getCacheObject(verifyKey); // 从缓存中获取验证码信息
redisCache.deleteObject(verifyKey); // 从缓存中删除验证码信息
if (captcha == null) { // 如果验证码信息为空
// 记录登录失败日志,并抛出 CaptchaExpireException 异常,表示验证码过期
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha)) { // 如果用户输入的验证码与缓存中的验证码不匹配
// 记录登录失败日志,并抛出 CaptchaException 异常,表示验证码错误
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
}
}
以上就是若依框架生成验证码的功能以及校验过程。