若依验证码
后端流程
验证码的调用接口为/captchaImage,整体的流程存放在ruoyi-admin模块下的com.ruoyi.web.controller.CaptchaController中
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
@Autowired
private ISysConfigService configService;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled)
{
return ajax;
}
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
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);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
}
}
第一步 是否开启验证码
这部分的代码逻辑存放在ruoyi-system模块中,是否开启验证码的相关配置存放在sys_config表
//controller
boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled)
{
return ajax;
}
//SysConfigServiceImpl
public boolean selectCaptchaEnabled()
{
String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
if (StringUtils.isEmpty(captchaEnabled))
{
return true;
}
return Convert.toBool(captchaEnabled);
}
通过传入config_key->sys.account.captchaEnabled得到验证码是否开启的相关配置,若是false直接返回,若是true继续下面的逻辑。
其中selectConfigByKey会先读取redis中的缓存,如果缓存中不存在数据再去读取数据库中的sys_config表
### 第二步 生成验证码
// 获取验证码的类型 math char
String captchaType = RuoYiConfig.getCaptchaType();
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
//captcha_codes:uuid拼接作为redis中的key
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码 math char
String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType))
{
// 7/1=?@7
String capText = captchaProducerMath.createText();
// 7/1=?
capStr = capText.substring(0, capText.lastIndexOf("@"));
// 7
code = capText.substring(capText.lastIndexOf("@") + 1);
//BufferedImage
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
//将captcha_codes:uuid 和 验证码的值7 保存到redis中
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
第三步 封装返回前端数据
BufferedImage
是其Image抽象类的实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中// 将图片读入内存 String imgPath = "D://demo.jpg"; BufferedImage image = ImageIO.read( new FileInputStream(imgPath) ); // 保存图片 File outputfile = new File("save.png"); ImageIO.write(bufferedImage, "png", outputfile);
FastByteArrayOutputStream
是Spring框架中的一个字节数组输出流,它是对Java标准库中ByteArrayOutputStream
的一个改进,提供了更高的性能和更低的内存占用
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid);
//base64对图片进行编码
//前端 this.imageUrl = "data:image/gif;base64," + res.img;
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
返回给前端的数据
前端流程
调用接口请求存放在 @/api/login
// 获取验证码
export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}
/views/login.vue
getCode() {
getCodeImg().then(res => {
//是否有验证码
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
}
});
}