框架默认集成了 字符型验证码 与 数学计算型验证码,两种类型的生成逻辑集中封装在 com.ruoyi.framework.web.service.CaptchaService 类中,且与框架配置体系、缓存组件深度联动,既保证了安全性,又支持灵活切换与扩展。本文将从配置源头、组件依赖、生成流程三个维度,拆解两种验证码的实现细节。
一、验证码类型的配置与生效机制
RuoYi 框架通过 配置驱动 实现验证码类型的灵活切换,无需修改代码即可在两种类型间切换,核心依赖配置文件与静态配置类的联动。
1.1 配置文件定义(application.yml)
框架在全局配置文件中预留了验证码类型配置项,ruoyi.captcha.type 字段支持 math(数学计算型)与 char(字符型)两种取值,默认通常为 math(安全性更高):
ruoyi:
captcha:
type: math # 验证码类型:math/char
expiration: 5 # 验证码过期时间(分钟,默认5分钟)
1.2 配置读取逻辑(RuoYiConfig 类)
框架通过 RuoYiConfig 静态配置类,将配置文件中的参数映射为可直接调用的方法,避免代码中硬编码配置值。核心代码如下:
/**
* 框架全局配置类
*/
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig {
// 验证码类型(math/char)
private String captchaType;
// 验证码过期时间(分钟)
private Integer captchaExpiration;
// 静态方法:供其他类直接获取验证码类型
public static String getCaptchaType() {
return SpringUtils.getBean(RuoYiConfig.class).captchaType;
}
// 静态方法:供其他类直接获取验证码过期时间
public static Integer getCaptchaExpiration() {
return SpringUtils.getBean(RuoYiConfig.class).captchaExpiration;
}
// getter/setter 省略
}
在 CaptchaService 中,只需通过 RuoYiConfig.getCaptchaType() 即可获取当前配置的验证码类型,为后续生成逻辑的分支判断提供依据:
// 从框架配置中读取当前启用的验证码类型
String captchaType = RuoYiConfig.getCaptchaType();
二、两种验证码的生成流程拆解
在 CaptchaService 的 getCode() 方法中,框架根据配置的验证码类型,调用对应的 Producer 实例生成验证码,核心流程可分为 “文本生成 → 内容拆分 → 图片渲染” 三步,两种类型的差异主要体现在 “文本生成与拆分” 环节。
2.1 数学计算型验证码(math)生成流程
数学型验证码的核心是 “分离展示内容与校验基准”—— 图片上显示数学表达式,Redis 中存储正确答案,避免直接暴露答案给前端。具体步骤如下:
生成 “表达式 @答案” 文本:
调用 captchaProducerMath.createText(),通过自定义的 KaptchaMathTextCreator 生成格式为 “表达式 @答案” 的字符串,例如 “3 * 5 = ?@15”。
拆分表达式与答案:
使用 lastIndexOf("@") 找到分隔符位置,截取 “@” 前的表达式作为 capStr(用于渲染图片),截取 “@” 后的数字作为 code(用于后续校验):
String capText = captchaProducerMath.createText();
// 表达式:如“3 * 5 = ?”(展示在图片上)
capStr = capText.substring(0, capText.lastIndexOf("@"));
// 答案:如“15”(存入Redis,用于校验)
code = capText.substring(capText.lastIndexOf("@") + 1);
渲染验证码图片:
调用 captchaProducerMath.createImage(capStr),将表达式渲染为带有蓝色文本、干扰线的图片,最终生成 BufferedImage 对象:
image = captchaProducerMath.createImage(capStr);
2.2 字符型验证码(char)生成流程
字符型验证码的逻辑相对简洁,生成的随机字符既是 “展示内容” 也是 “校验基准”,无需拆分,具体步骤如下:
生成随机字符文本:
调用 captchaProducer.createText(),基于 KaptchaConfig 中配置的字符集(0-9、A-Z)生成 4 位随机字符,例如 “8F2Z”。
统一赋值展示内容与校验基准:
由于字符本身就是答案,直接将生成的随机字符同时赋值给 capStr(渲染图片)与 code(存入 Redis):
// capStr与code一致:如“8F2Z”
capStr = code = captchaProducer.createText();
渲染验证码图片:
调用 captchaProducer.createImage(capStr),将随机字符渲染为带有黑色文本、干扰线的图片,生成 BufferedImage 对象:
image = captchaProducer.createImage(capStr);
9559

被折叠的 条评论
为什么被折叠?



