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

createh53周前 (02-24)技术教程5

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

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

@RestController
public class CaptchaController
{
    /** 省略部分注入的bean **/
    /**
     * 生成验证码
     */
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException
    {
        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地址开关
  addressEnabled: 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中,可以更新数据,不用一直新增。不过这种场景肯定还有很多别的方法去解决这个问题,这种方法应该也不是最好的一种,也欢迎大家讨论。

相关文章

那些年的QQ登录界面,你还记得吗,满满的全是回忆

刚上大学的时候,手机QQ软件不是很流行,因为除了一些品牌手机,其他国产手机基本不支持这个软件。那时候手机上网也是刚刚开始流行,5元30M流量,省着点用,是能坚持到月底的。那时候喜欢跟人聊qq,就用网页...

开始使用支付宝登录接口之前

开始使用支付宝登录接口之前,您需要先创建一个支付宝应用并将其注册到支付宝。这将为您提供一个应用 ID 和应用密钥,您需要在调用 API 时使用它们。获取用户授权要使用支付宝登录接口,您需要先从用户获取...

写了这么多年代码,这样的登录方式还是头一回见

Spring Security 系列还没搞完,最近还在研究。有的时候我不禁想,如果从 Spring Security 诞生的第一天开始,我们就一直在追踪它,那么今天再去看它的源码一定很简单,因为我们了...

用友NC系统“登陆后页面显示不完全”,怎么办?

用友NC系统使用过程中常见问题和解决方法:1、无法安装客户端插件,不能进入NC系统登陆界面问题现象现象1:可以打开web界面,但无法进入登陆界面,一直停留在右图所示界面。现象2:系统提示安全警告问题原...

「JWT」,你必须了解的认证登录方案

「JWT」,你必须了解的认证登录方案

作者:古时的风筝原文链接:https://www.cnblogs.com/fengzheng/p/13527425.htmlJWT 全称是 JSON Web Token,是目前非常流行的跨域认证解决方...

掏出手机,扫一扫,即刻登录——SpringBoot实现二维码扫码登录

二维码扫码登录已经成为了现代互联网时代的一种普遍的登录方式。它的出现,极大地方便了用户登录的流程,减少了用户输入用户名和密码的麻烦。在二维码扫码登录流程中,用户只需要通过扫描二维码的方式即可完成登录,...