使用redis保存验证码,传递给vue前端使用,包括后端登录验证

刚开始使redis,踩了不少坑,redis的key不好确定,前端用于刷新验证码不好找到一个确定的值,后面我是从后端给前端传送一个精确到毫秒的时间,前端在刷新验证码的时候,将这个时间传过来作为key使用,同时在登录的时候也传送这个时间戳过来,作为redis value的验证。

1、刷新验证码的时间

/**
     * 获取系统当前毫秒数
     * @since 2019-12-02
     * @return
     */
    @RequestMapping(value = "/redisVerifyCodeTime", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse redisVerifyCodeTime(HttpServletRequest request) {
        BaseResponse response = BaseResponse.success();
        try {
            Long oldtimestamp=System.currentTimeMillis();
            response.setExtData(ImmutableMap.builder().put("oldtimestamp", oldtimestamp).build());

        }catch (Exception e) {
            logger.error("redisVerifyCodeTime error", e);
            return BaseResponse.fail();
        }
        return response;

    }

 

2、生成验证码并保存到redis中,给前端传递的是一个图片

@RequestMapping("/redisVerifyCode")
public void verifyCode (HttpServletRequest request, HttpServletResponse response) {
    String oldtimestamp = request.getParameter("oldtimestamp");
    BufferedImage image = new BufferedImage(WIDTH, HIGHT,
            BufferedImage.TYPE_INT_RGB);
    // step2,获得画笔
    Graphics2D g = image.createGraphics();
    // step3,¸给画布填充一个随机的颜色
    SecureRandom r = new SecureRandom();
    try{
        r = SecureRandom.getInstance("SHA1PRNG");
    }catch(NoSuchAlgorithmException e){
        e.printStackTrace();
    }
    g.fillRect(0, 0, WIDTH, HIGHT);
    // step4, 在画布上绘画
    g.setColor(new Color(0, 0, 0));
    String str = "0123456789abcdefhijkmnpqrstuvwxyz0123456789ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
    String code = "";
    for (int i = 0; i < 4; i++) {
        g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
        int h = (int) (20 + 10 * r.nextDouble());
        g.setFont(new Font(null, h, h));
        String ch = String.valueOf(str.charAt(r.nextInt(str.length())));

        //增加验证码识别难度
        AffineTransform trans = new AffineTransform();
        double radians = Math.toRadians(Math.random() * 25.0D + 10.0D);
        int anchorx = 17 * i + 8;
        trans.rotate(radians, anchorx, 20.0D);

        float scaleSize = r.nextFloat() + 0.8F;
        if (scaleSize > 1.0F) {
            scaleSize = 1.0F;
        }
        trans.scale(scaleSize, scaleSize);
        g.setTransform(trans);

        g.drawString(ch, i * WIDTH / 5, h);

        code = code + ch;

    }
    //将验证码保存到redis中
    redisManager.put(VERIFYCODE_PREX + oldtimestamp, code, 10, TimeUnit.MINUTES);
    // 禁止图像缓存。
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setDateHeader("Expires", 0);
    response.setContentType("image/jpeg");
    try {
        OutputStream ops = response.getOutputStream();

        javax.imageio.ImageIO.write(image, "jpeg", ops);
    }catch (Exception e){
        e.printStackTrace();
    }

}

3、前端获取验证码

changeVerifyImg(){
      apiVerifyCodeTime({}).then(res => {
        if (res.resultCode == 1000) {//
          this.oldtimestamp = res.extData.oldtimestamp;
        } else {
          this.oldtimestamp = new Date().getTime();
        }
        this.verifyUrl = this.baseURL+'/globalmall/approvalForApp/redisVerifyCode?'+this.timeSign();
      }, err => {

      });
    },
    timeSign(){
      let obj = {oldtimestamp:this.oldtimestamp};
      obj = encryption(obj);
      return obj;
    }

4、前端登录实现

onSubmit() {
      // Disabled submit button
      this.beforeSubmit();

      console.log(sm4.encode({input:this.password,key:this.publicKey}));
      // Login...
      this.$store.dispatch('login',{
        userName: sm4.encode({input:this.userName,key:this.publicKey}),
        password: sm4.encode({input:this.password,key:this.publicKey}),
        verifyCode: sm4.encode({input:this.verifyCode,key:this.publicKey}),
        oldtimestamp: this.oldtimestamp
      }).then(res => {
        // Success handle
        if (res.resultCode == 1000) this.onSuccess(res);//登陆成功
        else {//提示框
          this.showConfirm = true;
          this.message = res.showMsg;
          this.changeVerifyImg();
        }
      }, err => {
        // Error handle
        this.onError(err);
        this.changeVerifyImg();
      })
    },

5、后端登录验证

 String oldtimestamp = request.getParameter("oldtimestamp");
           
            String userName = new SM4Utils().decode(request.getParameter("userName"), SM4_KEY);
            String password = new SM4Utils().decode(request.getParameter("password"), SM4_KEY);
            String verifyCode = new SM4Utils().decode(request.getParameter("verifyCode"), SM4_KEY);

            if(null == verifyCode || "".equals(verifyCode)){
                return BaseResponse.fail("验证码为空,请重新输入");
            }else if(!redisManager.exists(VERIFYCODE_PREX + oldtimestamp)){
                return BaseResponse.fail("验证码过期");
            }else if(!verifyCode.equalsIgnoreCase(redisManager.get(VERIFYCODE_PREX + oldtimestamp))){
                return BaseResponse.fail("验证码错误");
            }

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue前端和Java后端实现登录拦截并使用session,以下是详细的步骤: 1. 前端实现: 在Vue前端应用中,需要创建一个拦截器来拦截所有的请求,在请求头中添加token信息。在登录成功后,将后端返回的token存储在浏览器的本地存储(localStorage)中,每次发送请求时从本地存储中获取token并添加到请求头中,用于后端进行认证。 2. 后端实现: 在Java后端中,需要创建一个拦截器来验证请求头中的token信息,以确保用户登录有效。在用户登录验证成功后,生成一个session对象,并将其存储在服务器端(如Redis、数据库等)。 当用户发送请求时,后端拦截器首先从请求头中获取token信息,然后根据token从存储的session中查找对应的用户信息。如果找到用户信息,说明用户已登录,请求继续进行;如果未找到用户信息,说明用户未登录登录已过期,需要返回相应的错误信息给前端。 3. 登录过程: 前端后端发送登录请求,后端验证用户的用户名和密码是否正确,如果正确则生成一个唯一的token,并将其返回给前端前端收到token后将其存储在本地存储中。后续的请求均需要在请求头中携带该token。 4. 登出过程: 当用户点击退出登录按钮时,前端移除本地存储中的token,并向后端发送一个请求来销毁后端存储的session对象。 综上所述,通过前端拦截器和后端拦截器的配合,在前端发送请求时添加token信息,并在后端验证token信息来实现登录拦截。通过session机制,后端可以在多次请求之间保存用户的登录状态,确保用户的合法性和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值