验证码功能的实现


验证码操作处理


@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;
    }

   这里首先进行了一次判断,如果验证码可用,就直接返回操作成功的消息;如果验证码不可用(未生成/已失效),那就再生成一个。

验证码生成步骤:

  1. 生成验证码的ID。
  2. 生成保存在redis中需要用到的Key值。
  3. 从配置类中提取验证码的种类。
  4. 如果是数学类型的验证码,就利用接口生成一个文本(如:0/1=?@0),然后将文本内容切割为问题和答案两部分,将问题部分利用接口写入验证码图片中;如果是字符类型,就直接获取字符内容作为答案,然后将字符写入图片中。
  5. 将验证码的答案和生成的Key值一起存入Redis中。
  6. 将图片信息写入到输出流中,如果出现问题就抛出异常。
  7. 输出流将图片转换为二进制序列,然后进行一次Base64加密后和ID一起放入Ajax消息体中。
  8. Ajax会将消息体传回前端。
Logo

快速构建 Web 应用程序

更多推荐