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

相关推荐
程序员张31 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
麦兜*8 小时前
Spring Boot启动优化7板斧(延迟初始化、组件扫描精准打击、JVM参数调优):砍掉70%启动时间的魔鬼实践
java·jvm·spring boot·后端·spring·spring cloud·系统架构
KK溜了溜了8 小时前
JAVA-springboot 整合Redis
java·spring boot·redis
大只鹅8 小时前
解决 Spring Boot 对 Elasticsearch 字段没有小驼峰映射的问题
spring boot·后端·elasticsearch
天河归来8 小时前
使用idea创建springboot单体项目
java·spring boot·intellij-idea
IT_10249 小时前
Spring Boot项目开发实战销售管理系统——数据库设计!
java·开发语言·数据库·spring boot·后端·oracle
武昌库里写JAVA9 小时前
Oracle如何使用序列 Oracle序列使用教程
java·开发语言·spring boot·学习·课程设计
超级小忍10 小时前
Spring Boot 中常用的工具类库及其使用示例(完整版)
spring boot·后端
程序员张310 小时前
SQL分析与打印-p6spy组件
spring boot·sql·mybatis·mybatisplus·p6spy
CHENWENFEIc11 小时前
SpringBoot论坛系统安全测试实战报告
spring boot·后端·程序人生·spring·系统安全·安全测试