您的位置 首页 java

若依开发框架解析笔记(2)-登录验证码生成解析

这篇笔记的内容主要讲解后台登陆生成验证码相关的内容。在前后端工程都顺利启动之后,打开网页,可以使用浏览器的开发者工具,可以查看http的请求和响应情况,根据url可以快速定位到后端的具体的控制层的方法。

我们可以看到打开首页之后,就是登陆的页面,我们主要关注一点是图片里面的那个请求/dev-api/captchaImage,这个方法是后端生成验证码的方法,验证码生成的主要代码在CaptchaController.java里面。下面着重介绍一下生成验证码的主要思路和流程:

 @RestController
public class CaptchaController
{
    /** 省略部分注入的 bean  **/    /**
     * 生成验证码
     */    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IO Exception 
    {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaOnOff = configService.selectCaptchaOnOff();
        ajax.put("captchaOnOff", captchaOnOff);
         if  (!captchaOnOff)
        {
            return ajax;
        }

        // 保存验证码信息
         String  uuid = IdUtils.simpleUUID();
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;

        String capStr = null, code = null;
        BufferedImage image = null;    

这个框架后台会封装一个统一的名字叫AjaxResult的类,然后把内容返回给前台。首先会校验一下是否开启了验证码,如果是false,则不需要输入验证码。这个内容的读取是通过注入一个配置类来实现的,对应的数据库中的表的截图如下:


  @Autowired
   private  ISysConfigService configService;  

如果把sys_config表中的true改成false,重新启动后台工程,则登录不需要使用验证码,直接就会把封装好的AjaxResult返回。

判断完成是否开启验证码之后的第一步是调用一个封装好的工具类生成一个uuid,结果会是一个随机的 字符串 。下一步会调用封装好的常量,表明这个字符串是用于验证码的,以便后续存入 redis 中。 debug 的结果如下图所示,作者是通过 冒号 来分割开值的类型和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);  

生成的图片首先选项有两种,数字和字母,配置的读取来自于工程中的配置文件。

 ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.2
  # 版权年份
  copyrightYear: 2022
  # 实例演示开关
  demoEnabled: true
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath, Linux 配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
   address Enabled: false
  # 验证码类型 math 数组计算 char 字符验证
  captchaType: math  

其中的captchaType这个选项决定了验证码是字符还是数字,配置类如何与配置文件映射的方法在第一篇笔记中已经介绍了,后续生成图片则使用了 google 的kaptcha框架,具体这个框架的原理不在这里介绍了。

如果选择数字的方式生成验证码,会生成出 运算的题和答案(8-7=?@1),并且中间通过@符号分开,分隔开之后的前半部分生成图片,后半部分的答案和之前的uuid一起存入redis中。最后的部分是把生成的图片通过Base64进行编码,把uuid和编码好的图片返回给前台。

         ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));  

总结一下验证码相关的生成流程,首先生成一个uuid,然后验证码生成计算题的问题和答案,把答案和uuid存入redis,问题和uuid传回前台。

不过这个方案,如果有人一直不进行登录,一直恶意快速刷新登录的页面,会造成redis数据库里面写入很多数据,如果数据在redis中保存的时间比较久的话会对redis数据库造成一定的压力。要解决这个问题的话,仅仅使用后台不一定能够解决这个问题。如果前台服务器使用 nginx 这种网关的话,可以通过 HTTP_X_FORWARDED_FOR来获取用户的真实ip,后端接收到请求之后,拿到相关参数,并且可以把HTTP_X_FORWARDED_FOR的值也一并存入redis中,可以更新数据,不用一直新增。不过这种场景肯定还有很多别的方法去解决这个问题,这种方法应该也不是最好的一种,也欢迎大家讨论。

文章来源:智云一二三科技

文章标题:若依开发框架解析笔记(2)-登录验证码生成解析

文章地址:https://www.zhihuclub.com/201089.shtml

关于作者: 智云科技

热门文章

网站地图