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

相关推荐
will_we20 分钟前
Spring Boot4先行篇:第一篇 Spring Boot 创建 Docker 镜像
spring boot
Q_Q19632884751 小时前
python+django/flask基于协同过滤算法的理财产品推荐系统
spring boot·python·django·flask·node.js·php
码起来呗1 小时前
基于Spring Boot的乡村拼车小程序的设计与实现-项目分享
spring boot·后端·小程序
亚林瓜子4 小时前
Spring中的异步任务(CompletableFuture版)
java·spring boot·spring·async·future·异步
MuYiLuck4 小时前
redis持久化与集群
java·数据库·redis
埃泽漫笔4 小时前
Redis性能优化避坑指南
redis
升鲜宝供应链及收银系统源代码服务4 小时前
升鲜宝生鲜配送供应链管理系统--- 《多语言商品查询优化方案(Redis + 翻译表 + 模糊匹配)》
java·数据库·redis·bootstrap·供应链系统·生鲜配送·生鲜配送源代码
JH30734 小时前
Redis 中被忽视的“键过期策略”与内存回收机制
数据库·redis·缓存
Microsoft Word4 小时前
Redis常见面试题
数据库·redis·缓存
bing.shao5 小时前
mongodb与redis在聊天场景中的选择
数据库·redis·mongodb