大型纪录片:学习若依源码(前后端分离版)之 “ 验证码功能及登录功能实现”

前言

既然能刷到这篇文章,代表你应该也知道若依是用来干嘛的了,只是可能你还没那么理解,刚好最近有些时间,想重头开始重新阅读这个框架,故开创这个系列,希望能和你们一起学习,共同进步!(关注我,不迷路(❁´◡`❁))

验证码模块

验证码生成的主要步骤:

  1. 前端发出请求
  2. 后端生成一个表达式,如3+1=4
  3. 表达式的形式实际上是 3+1=?@4
  4. 3+1=? 转成图片,4存入Redis

前端代码实现

验证码是在登录的时候用到,所以我们看到login.vue
图一
根据这里给出的信息,我们可以发现验证码是和loginform里面的code绑定在一起。下方div装着的就是对应着验证码的图片啦。

可以看到图片上面还有一个单击事件,顾名思义就是获取、刷新验证码图片的。我们来看看这个方法
图二
如图所示,在页面创建的时候,会主动调用一次该方法(因为我们进入页面的时候,验证码是要加载好的),在点击图片的时候,该函数会向引入的"@/api/login"里面去找对应的方法去发送请求。并返回一个promise对象。

图三
这里解释一下为什么是返回request呢?我们顺藤摸瓜发现这个request是被封装过的,再进入request.js我们可以看到以下:

图四request 吉尔斯里面封装了axios

图五
‘/dev-api’ 为统一前缀

图六
由图六可见,captchaImage请求有个统一前缀dev-api,并且请求的是localhost:80,也就是请求的是前端。这其实是为了解决跨域问题,若依是在前端通过反向代理来解决的,URL请求前端,然后再映射到后端,具体配置见vue.config.js文件。

图七
这里可以看到前缀被替换为空了,然后统一换成了localhost:8080

后端代码实现

顺藤摸瓜根据前端给出的路径,我们找到了“/ captchaImage”方法。这个方法就是核心的验证码实现方法了,判断是否打开了验证码,使用了什么类型的验证码,并生成验证码放入redis。这里我把代码贴出来,供大家学习:

 /**
     * 生成验证码
     */
    @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;

        // 生成验证码
        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); //captcha_expiration 表示验证码过期时间
        // 转换流信息写出
        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;
    }

若依将后端响应给前端的数据封装成一个AjaxResult对象(继承自HashMap),篇幅问题就不贴贴了。

然后请求configService.selectCaptchaOnOff(); 方法查看验证码功能是否打开,若是没有打开,直接返回成功请求的信息,要是打开了,再去生成、保存二维码;来看看它是怎么判断验证码开关是否打开的,点进去该方法可以看到
图八
然后再进selectConfigByKey方法

图九
总结一下这两个方法就是,去redis里面查找"sys.account.captchaOnOff"为存储在redis中的key,该参数表面验证码开关是否打开,要是redis里面没有这个key,就去数据库里面查找出这个key,然后将它保存到redis里面。

图十

这下我们就很清晰了。这也是整个验证码功能的后端实现。RDM查看Redis中的键值对:

  • key为统一前缀:uuid
  • value为表达式答案
  • ttl:键值对超时剩余时间

登录模块

前端代码实现

接下来再来看登录实现,登录主要步骤:

  1. 校验验证码
  2. 校验用户名密码
  3. 生成Token令牌

和验证码类似,这里就简单展示一下前端代码
图十一
图十二
通过浏览器查看点击登录按钮后请求的URL来看后端代码……

后端代码实现

图十三
登录成功后,我们发现它是首先请求了一个login方法,然后再请求了getinfo和getRouters方法,他们分别对应的功能为

  • login:验证登录信息
  • getInfo:获取当前用户的角色和权限信息,存储在Vuex中
  • getRouters:根据当前用户的权限获取动态路由

先来看看‘/login’请求。
图十三
ctrl + 鼠标左键,进入到loginService的login方法,可以看到登录的具体流程,如下图所示:
图十四
这里判断校验码开关是否为开,是即为true,进入校验。

图十五
这里使用了spring security框架

图十六
这里用了异步去记录日志,AsyncManager为一个异步任务管理器,感兴趣可以点进去看作者是如何封装的;最后就是记录登录信息,然后生成token。到这里登录功能就完成了。剩下的就是返回该角色的一些信息之类的。

总结

今天讲的是验证码及登录的实现,好久没写博客了不知道写得咋样,可能有些地方讲的也不是很清楚吧,如果有什么错误,还希望大家指出,一起学习嘛。也可以在评论区一起学习交流啊~

那么以上就是唐某的一些理解。这次的分享就到这里了。记得一键三连~( •̀ ω •́ )✧

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐