【第4章】SpringBoot实战篇之登录优化(含redis使用)

文章目录


前言

上一章的登录接口,我们将用户登录信息放置于Map中,存在一个问题,集群部署无法共享以及应用停止用户登录信息即丢失,接下来我们整合redis来整合这个问题。


一、整合redis

1. 引入库

bash 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 配置

bash 复制代码
spring:
  data:
    redis:
      host: 192.168.137.192
      port: 6379
      database: 0
      username: default
      password: 21797d7480c1270b848a1524128671b31dcad0725762cf41cc81c21e15fa35b2

二、登录优化

1.登录

java 复制代码
@Autowired
StringRedisTemplate stringRedisTemplate;
@RequestMapping("login")
public Result login(@Valid User loginUser){
    String message="用户名/密码不正确";
    User user = userSerivce.findUserByName(loginUser.getUsername());
    if(user!=null){//用户存在
        if(user.getPassword().equals(Md5Util.getMD5String(loginUser.getPassword()))){//密码正确
            Map<String,Object> claims=new HashMap();
            claims.put("userId",user.getId());
            claims.put("username",user.getUsername());
            String token = JwtUtils.create(claims);
            stringRedisTemplate.opsForValue().set(user.getId().toString(),token,24, TimeUnit.HOURS);
            return Result.success("登录成功",token);
        }
    }
    return Result.error(message);
}

2.拦截器

java 复制代码
@Autowired
StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String token = request.getHeader("Authorization");
    if(token!=null&&token.contains("Bearer")){
        String tokenStr = token.substring(token.indexOf("Bearer") + 7);
        boolean verify = JwtUtils.verify(tokenStr);
        if(verify){//此处解析loginUsers,验证用户已登录
            Map<String, Object> claims = JwtUtils.getClaims(tokenStr);
            if(tokenStr.equals(stringRedisTemplate.opsForValue().get(claims.get("userId").toString()))){
                ThreadLocalUtil.set(claims);//用户信息放置ThreadLocal
                return true;
            };
        }
    }
    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    response.setContentType("application/json;charset=UTF-8");
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.writerFor(Result.class);
    String message = objectMapper.writeValueAsString(Result.error("token验证失败,请重新获取token后重试!"));
    response.getWriter().println(message);
    return false;
}

3. 登出

bash 复制代码
@RequestMapping("logout")
public Result logout(@Valid User loginUser,@RequestHeader("Authorization") String token){
    String message="用户名/密码不正确";
    User user = userSerivce.findUserByName(loginUser.getUsername());
    if(user!=null){//用户存在
        if(token!=null&&token.contains("Bearer")){
            String tokenStr = token.substring(token.indexOf("Bearer") + 7);
            boolean verify = JwtUtils.verify(tokenStr);
            if(verify&&tokenStr.equals(loginInceptor.get(user.getId()))){
//                    loginInceptor.remove(user.getId());
                stringRedisTemplate.delete(user.getId().toString());
                return Result.success("登出成功");
            }
        }
    }
    return Result.error(message);
}

4. 修改密码

bash 复制代码
@PatchMapping("updatePwd")
    public Result updatePwd(@RequestBody Map<String,String> params){
        String oldPwd = params.get("old_pwd");
        String newPwd = params.get("new_pwd");
        String conPwd = params.get("con_pwd");
        //参数校验
        if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(conPwd)){
            return Result.error("缺少必要的参数");
        }
        if(!validPwdLen(oldPwd)||!validPwdLen(newPwd)||!validPwdLen(conPwd)){
            return Result.error("密码为8-20位");
        }
        //密码匹配
        Map<String, Object> claims =ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("userId");
        User user = userSerivce.findUserById(userId);
        if(!Md5Util.getMD5String(oldPwd).equals(user.getPassword())){
            return Result.error("密码有误");
        }
        //新密码匹配
        if(!newPwd.equals(conPwd)){
            return Result.error("两次密码不匹配");
        }
        //新旧匹配
        if(newPwd.equals(oldPwd)){
            return Result.error("新旧密码不能相同");
        }
        user.setPassword(Md5Util.getMD5String(newPwd));
        int i = userSerivce.UpdateUser(user);
        if(i!=1){
            return Result.success("密码修改失败");
        }
        stringRedisTemplate.delete(user.getId().toString());
        return Result.success("密码修改成功");
    }

总结

回到顶部

更多关于redis内容请参考redis系列专栏

相关推荐
lifewange4 小时前
Redis 集合(Set)运算完全指南
数据库·chrome·redis
Full Stack Developme5 小时前
Spring Boot 事务管理完整教程
java·数据库·spring boot
phltxy7 小时前
Redis 主从复制
java·数据库·redis
ShiJiuD6668889998 小时前
大事件板块三
前端·bootstrap·html
shixiaoyu6668 小时前
Redis主从原理及哨兵搭建
redis
环流_9 小时前
redis:持久化rdb
java·数据库·redis
難釋懷9 小时前
Redis通信协议-基于Socket自定义Redis的客户端
数据库·redis·缓存
环流_9 小时前
redis:AOF
数据库·redis·spring
半夜修仙10 小时前
Redis入门
数据库·redis·缓存
夕除12 小时前
spring boot 6
java·spring boot·后端