开源项目renren-fast的验证码以及登录认证流程分析

9 篇文章 1 订阅

一、验证码的获取

  • 查看其项目源码,在跳转到登录页面后,调用created钩子函数,而调用的这个getCaptcha(),方法就是请求获取验证码的方法。而且注意,在其请求验证码的时候,携带了uuid参数,并且将这个uuid参数赋值给了this.dataForm.uuid。此时vue对象的data属性上的dataForm登录表单对象就有了这个uuid值,这个参数怎么用下面再说。
 created () {
      this.getCaptcha()
  },
 getCaptcha () {
        this.dataForm.uuid = getUUID()
        this.captchaPath = this.$http.adornUrl(`/captcha.jpg?uuid=${this.dataForm.uuid}`)
    }
  • 再看其后端代码
@GetMapping("captcha.jpg")
	public void captcha(HttpServletResponse response, String uuid)throws IOException {
		response.setHeader("Cache-Control", "no-store, no-cache");
		response.setContentType("image/jpeg");

		//获取图片验证码
		BufferedImage image = sysCaptchaService.getCaptcha(uuid);

		ServletOutputStream out = response.getOutputStream();
		ImageIO.write(image, "jpg", out);
		IOUtils.closeQuietly(out);
	}

我们找到后端的接口,也就是captcha方法,这个方法就是设置响应类型,然后调用sysCaptchaService的getCaptcha这个方法。

    public BufferedImage getCaptcha(String uuid) {
        if(StringUtils.isBlank(uuid)){
            throw new RRException("uuid不能为空");
        }
        //生成文字验证码
        String code = producer.createText();

        SysCaptchaEntity captchaEntity = new SysCaptchaEntity();
        captchaEntity.setUuid(uuid);
        captchaEntity.setCode(code);
        //5分钟后过期
        captchaEntity.setExpireTime(DateUtils.addDateMinutes(new Date(), 5));
        this.save(captchaEntity);

        return producer.createImage(code);
    }

继续看这个方法,这个方法生成了code,过期时间,并和uuid一起组成了一个 验证码对象,保存到了数据库当中。当做完这些操作后,将生成的图片响应给前端。

验证码的逻辑总结如下图:
在这里插入图片描述

二、登录逻辑

  • 登录按钮触发的是dataFormSubmit 方法,我们看这个方法的处理逻辑。
dataFormSubmit () {
        this.$refs['dataForm'].validate((valid) => {
          if (valid) {
            this.$http({
              url: this.$http.adornUrl('/sys/login'),
              method: 'post',
              data: this.$http.adornData({
                'username': this.dataForm.userName,
                'password': this.dataForm.password,
                'uuid': this.dataForm.uuid,
                'captcha': this.dataForm.captcha
              })
            }).then(({data}) => {
              if (data && data.code === 0) {
                this.$cookie.set('token', data.token)
                this.$router.replace({ name: 'home' })
              } else {
                this.getCaptcha()
                this.$message.error(data.msg)
              }
            })
          }
        })
      },

从这个方法可以看出,在请求/sys/login接口时,携带的参数是
username:对应我们输入的用户名
password:对应我们输入的密码
uuid:注意这个uuid就是当时请求验证码时携带的uuid
captcha:我们输入的验证码

  • 查看后端登录接口
	@PostMapping("/sys/login")
	public Map<String, Object> login(@RequestBody SysLoginForm form)throws IOException {
		boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
		if(!captcha){
			return R.error("验证码不正确");
		}

		//用户信息
		SysUserEntity user = sysUserService.queryByUserName(form.getUsername());

		//账号不存在、密码错误
		if(user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
			return R.error("账号或密码不正确");
		}

		//账号锁定
		if(user.getStatus() == 0){
			return R.error("账号已被锁定,请联系管理员");
		}

		//生成token,并保存到数据库
		R r = sysUserTokenService.createToken(user.getUserId());
		return r;
	}

分析下面这个方法

boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());

查看这个方法的实现

    @Override
    public boolean validate(String uuid, String code) {
        SysCaptchaEntity captchaEntity = this.getOne(new QueryWrapper<SysCaptchaEntity>().eq("uuid", uuid));
        if(captchaEntity == null){
            return false;
        }

        //删除验证码
        this.removeById(uuid);

        if(captchaEntity.getCode().equalsIgnoreCase(code) && captchaEntity.getExpireTime().getTime() >= System.currentTimeMillis()){
            return true;
        }

        return false;
    }

看到这里,uuid的作用应该就明白了,根据这个uuid去查找数据库保存的验证码,然后比对数据库中的验证码和用户输入的是否一致,如果一致且未过期,则返回true。

  • 总结登录流程图如下:

在这里插入图片描述
在这里插入图片描述

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值