【第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系列专栏

相关推荐
福大大架构师每日一题1 天前
Redis 8.10.0 正式发布:紧凑哈希、批量导入、备份恢复、流与时序能力全面升级
数据库·redis·哈希算法
祈禾1 天前
Redis三大特殊数据类型
运维·服务器·数据库·redis·笔记·缓存
y = xⁿ1 天前
一文掌握Redis常见八股
数据库·redis·缓存
山荷枝1 天前
04-框架--SpringBoot
java·spring boot·后端
用户3126874877201 天前
你的配置真的绑定上了吗?Spring Boot @ConfigurationProperties 全链路拆解
spring boot
2601_963870221 天前
【计算机毕业设计】基于Spring Boot+Vue的高考志愿填报系统的设计与实现
spring boot·课程设计·高考
andongni2031 天前
SpringBoot 入门实验报告
java·spring boot·后端
2601_953824611 天前
【计算机毕业设计】基于Spring Boot+Vue的家电购物系统的设计与实现
spring boot·后端·课程设计
码农进化录1 天前
Java 程序员的 AI 进化论 | 用 AI 生成 Spring Boot 脚手架,省下两小时重复劳动
java·spring boot·openai
paopaokaka_luck1 天前
基于springboot3+vue3的美妆商城平台(AI问答、协同过滤算法、支付宝沙盒支付、物流快递api、Echarts图形化分析)
java·前端·spring boot·学习·maven·echarts