Springboot项目中利用redis优化登录模块

1.需要优化的模块

  • 1.使用redis存储验证码
    • 验证码需要频繁的访问与刷新,对性能的要求较高
    • 验证码不需永久的保存,通常在很短的时间后就会失效
    • 分布式部署时,存在session共享的问题
  • 2.使用redis存储登录凭证
    • 每次处理请求时,都要查询用户的登录凭证,访问的频率非常高
  • 3.使用redis缓存用户信息
    • 处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高

2.验证码优化

  • 之前是将这个验证放入了session中,这样以后分布式部署也会有问题,所有我们用redis来存储,并将其设置为60s后过期。
  • 编写获取key的方法

	private static final String PREFIX_KAPTCHA = "kaptcha";
/**
     * 登录验证码
     */
    public static String getKaptchaKey(String owner){
        return PREFIX_KAPTCHA + SPLIT + owner;
    }
  • 更改登录的controller
@RequestMapping(path = "/kaptcha", method = RequestMethod.GET)
    public void getKaptcha(HttpServletResponse response/*, HttpSession session*/){
        // 生成验证码
        String text = kaptchaProducer.createText();
        BufferedImage image = kaptchaProducer.createImage(text);

        // 将验证码存入session
        //session.setAttribute("keptcha", text);


        // 验证码的所有者
        String keptchaOwner = CommunityUtil.generateUUID();
        Cookie cookie = new Cookie("keptchaOwner", keptchaOwner);
        cookie.setMaxAge(60);
        cookie.setPath(contextPath);
        response.addCookie(cookie);

        // 将验证码存入redis
        String rediskey = RedisKeyUtil.getKaptchaKey(keptchaOwner);
        redisTemplate.opsForValue().set(rediskey, text, 60, TimeUnit.SECONDS);



        // 将图片输出给浏览器
        response.setContentType("image/png");
        try {
            OutputStream os = response.getOutputStream();
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
            logger.error("响应验证码失败:" + e.getMessage());
        }
    }

    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public String login(String username, String password, String code, boolean rememberme,
                        Model model/*, HttpSession session*/, HttpServletResponse response,
                        @CookieValue("keptchaOwner") String keptchaOwner){
        // 检查验证码
        //String keptcha = (String) session.getAttribute("keptcha");

        String keptcha = null;
        if(StringUtils.isNotBlank(keptchaOwner)){
            String redisKey = RedisKeyUtil.getKaptchaKey(keptchaOwner);
            keptcha = (String) redisTemplate.opsForValue().get(redisKey);
        }

        //System.out.println(code + " " + keptcha);
        if(StringUtils.isBlank(code) || StringUtils.isBlank(keptcha) || !(keptcha.equalsIgnoreCase(code))){
            model.addAttribute("codeMsg", "验证码不正确!");
            return "/site/login";
        }

        // 检查账号, 密码
        int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
        System.out.println(expiredSeconds);
        Map<String, Object> map = userService.login(username, password, expiredSeconds);
        if(map.containsKey("ticket")){
            Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
            cookie.setPath(contextPath);
            cookie.setMaxAge(expiredSeconds);
            response.addCookie(cookie);
            return "redirect:/index";
        }else{
            model.addAttribute("usernameMsg", map.get("usernameMsg"));
            model.addAttribute("passwordMsg", map.get("passwordMsg"));
            return "/site/login";
        }

    }

3.使用redis存储登录凭证

  • 同样的也是先创建一个key
	private static final String PREFIX_TICKET = "ticket";
/**
     * 登录的凭证
     */
    public static String getTicketKey(String ticket){
        return PREFIX_TICKET + SPLIT + ticket;
    }
  • 改造UserService
//loginTicketMapper.insertLoginTicket(loginTicket);
        String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
        redisTemplate.opsForValue().set(redisKey, loginTicket);


//        loginTicketMapper.updateStatus(ticket, 1);
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey);
        loginTicket.setStatus(1);
        redisTemplate.opsForValue().set(redisKey, loginTicket);


//return loginTicketMapper.selectByTicket(ticket);
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        return (LoginTicket) redisTemplate.opsForValue().get(redisKey);

4.使用redis缓存用户信息

  • 创建key
	private static final String PREFIX_USER = "user";
/**
     * 用户
     */
    public static String getUserKey(int userId){
        return PREFIX_USER + SPLIT + userId;
    }
  • 修改userservice
//return userMapper.selectById(id);
        User user = getCache(id);
        if(user == null){
            user = initCache(id);
        }

        return user;

userMapper.updateStatus(userId, 1);
            clearCache(userId);

 int rows =  userMapper.updateHeader(userId, headerUrl);
        clearCache(userId);

userMapper.updatePassword(id,password);
        clearCache(id);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值