验证码功能的实现
验证码操作处理
@RestController
public class CaptchaController {
-
@RestController :是@Controller 和 @ResponseBody 的结合。
-
@Controller 注解标识的类,代表了控制器类(控制层/表现层)。这里控制层里面的每个方法,都可以去调用@Service标识的类(业务逻辑层)。
-
@ResponseBody注解标识的类,将返回的对象通过适当的转换器转换为指定的格式之后,写入到Response对象的body区,通常用来返回JSON数据或者是XML数据。
-
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
@Autowired
private ISysConfigService configService;
-
@Resource:指定 name 时,会根据 name 寻找对应的 bean (bean 就是一个封装好的类),然后根据 bean 中的内容对注解标识的对象进行自动装配。
-
@Autowired:默认按照类型进行寻找,寻找到对应的 bean 后进行自动装配。
-
captchaProducer: 验证码生成器;
-
captchaProducerMath: 验证码生成器(数学形式的验证码);
-
redisCache: redis缓存;
-
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;
}
这里首先进行了一次判断,如果验证码可用,就直接返回操作成功的消息;如果验证码不可用(未生成/已失效),那就再生成一个。
验证码生成步骤:
- 生成验证码的ID。
- 生成保存在redis中需要用到的Key值。
- 从配置类中提取验证码的种类。
- 如果是数学类型的验证码,就利用接口生成一个文本(如:0/1=?@0),然后将文本内容切割为问题和答案两部分,将问题部分利用接口写入验证码图片中;如果是字符类型,就直接获取字符内容作为答案,然后将字符写入图片中。
- 将验证码的答案和生成的Key值一起存入Redis中。
- 将图片信息写入到输出流中,如果出现问题就抛出异常。
- 输出流将图片转换为二进制序列,然后进行一次Base64加密后和ID一起放入Ajax消息体中。
- Ajax会将消息体传回前端。