找回密码
 立即注册
查看: 3|回复: 0

38,令牌主动失效redis,SpringBoot集成redis

[复制链接]

243

主题

6

精华

247

金币

技术维护QQ:515138

积分
530
发表于 昨天 10:10 | 显示全部楼层 |阅读模式
38,令牌主动失效redis
登录成功后,给浏览器响应令牌的同时,把该令牌存储到redis中
LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌
当用户修改密码成功后,删除redis中存储的旧令牌
1.jpg
1,引入redis依赖:
  1. <!--redis依赖-->
  2.         <dependency>
  3.             <groupId>org.springframework.boot</groupId>
  4.             <artifactId>spring-boot-starter-data-redis</artifactId>
  5.         </dependency>
复制代码
2,yml配置
  1. spring:
  2.   profiles:
  3.     active: dev
  4.   application:
  5.     name: JinheiNew
  6.   datasource:
  7.     driver-class-name: com.mysql.cj.jdbc.Driver
  8.     url: jdbc:mysql://localhost:3306/big_event?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
  9.     username: root
  10.     password: root
  11.   # redis配置
  12.   data:
  13.     redis:
  14.       host: localhost
  15.       port: 6379
  16.       connect-timeout: 5000
复制代码
3,C层使用:
  1. package com.jinhei.controller;
  2. import com.jinhei.pojp.Result;
  3. import com.jinhei.pojp.User;
  4. import com.jinhei.service.UserService;
  5. import com.jinhei.utils.JwtUtils;
  6. import com.jinhei.utils.Md5Util;
  7. import com.jinhei.utils.ThreadLocalUtil;
  8. import io.swagger.v3.oas.annotations.Operation;
  9. import io.swagger.v3.oas.annotations.tags.Tag;
  10. import jakarta.validation.constraints.Pattern;
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.hibernate.validator.constraints.URL;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.data.redis.core.StringRedisTemplate;
  15. import org.springframework.data.redis.core.ValueOperations;
  16. import org.springframework.util.StringUtils;
  17. import org.springframework.validation.annotation.Validated;
  18. import org.springframework.web.bind.annotation.*;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import java.util.concurrent.TimeUnit;
  22. /**
  23. * 用户相关接口
  24. */
  25. @Tag(name = "用户相关接口")
  26. @RestController
  27. @RequestMapping("/user")
  28. @Slf4j
  29. @Validated
  30. public class UserController {
  31.     @Autowired
  32.     private UserService userService;
  33.     @Autowired
  34.     private StringRedisTemplate stringRedisTemplate;
  35.     /**
  36.      * 用户注册
  37.      */
  38.     @Operation(summary = "创建用户",description = "根据姓名创建用户")
  39.     @PostMapping("/register")
  40.     public Result register(@Pattern(regexp = "^[a-zA-Z0-9_-]{4,20}$") String username,@Pattern(regexp = "^[a-zA-Z0-9_-]{6,20}$") String password) {
  41.         log.info("用户注册:username={},password={}", username, password);
  42.             // 查看用户是否存在
  43.             User user = userService.findByUsername(username);
  44.             // 注册用户
  45.             if (user == null){
  46.                 userService.register(username, password);
  47.                 return Result.success();
  48.             }else {
  49.                 return Result.error("用户已存在");
  50.             }
  51.         }
  52.     /**
  53.      * 用户登录
  54.      */
  55.     @PostMapping("/login")
  56.     public Result login(@Pattern(regexp = "^[a-zA-Z0-9_-]{4,20}$") String username,@Pattern(regexp = "^[a-zA-Z0-9_-]{6,20}$") String password) {
  57.         log.info("用户登录:username={},password={}", username, password);
  58.         // 查看用户是否存在
  59.         User user = userService.findByUsername(username);
  60.         // 登录用户
  61.         if (user == null){
  62.             return Result.error("用户不存在");
  63.         }
  64.        if (Md5Util.getMD5String(password).equals(user.getPassword())){
  65.            // 登录成功
  66.            // 生成JWT令牌
  67.            Map<String, Object> claims = new HashMap<>();
  68.            claims.put("id", user.getId());
  69.            claims.put("username", user.getUsername());
  70.            String token = JwtUtils.generateJwt(claims);
  71.            // 存储在redis中
  72.            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
  73.            operations.set(token, token,2, TimeUnit.HOURS); // 2小时
  74.            return Result.success(token);
  75.        }
  76.        return Result.error("密码错误");
  77.     }
  78.     /**
  79.      * 获取用户信息
  80.      */
  81.     @GetMapping("/userInfo")
  82.     public Result<User> userInfo(/*@RequestHeader(name = "Authorization") String token*/) {
  83.         //根据用户名查询用户
  84.        /* Map<String, Object> map = JwtUtils.parseJWT(token);
  85.         String username = (String) map.get("username");*/
  86.         Map<String, Object> map = ThreadLocalUtil.get();
  87.         String username = (String) map.get("username");
  88.         User user = userService.findByUsername(username);
  89.         return Result.success(user);
  90.     }
  91.     /**
  92.      * 修改用户信息
  93.      */
  94.     @PutMapping("/update")
  95.     public Result update(@RequestBody @Validated User user) {
  96.         userService.update(user);
  97.         return Result.success();
  98.     }
  99.     /**
  100.      * 修改用户头像
  101.      */
  102.     @PatchMapping("/updateAvatar")
  103.     public Result updateAvatar(@RequestParam @URL String avatarUrl) {
  104.         userService.updateAvatar(avatarUrl);
  105.         return Result.success();
  106.     }
  107.     /**
  108.      * 修改密码
  109.      */
  110.     @PatchMapping("/updatePwd")
  111.     public Result updatePwd(@RequestBody Map<String, String> params,@RequestHeader(name = "Authorization") String token) {
  112.         log.info("param信息{}", params);
  113.         //1.校验参数
  114.         String oldPwd = params.get("old_pwd");
  115.         String newPwd = params.get("new_pwd");
  116.         String rePwd = params.get("re_pwd");
  117.         if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)) {
  118.             return Result.error("缺少必要的参数");
  119.         }
  120.         //原密码是否正确
  121.         //调用userService根据用户名拿到原密码,再和old_pwd比对
  122.         Map<String,Object> map = ThreadLocalUtil.get();
  123.         String username = (String) map.get("username");
  124.         User loginUser = userService.findByUsername(username);
  125.         if (!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
  126.             return Result.error("原密码填写不正确");
  127.         }
  128.         //newPwd和rePwd是否一样
  129.         if (!rePwd.equals(newPwd)){
  130.             return Result.error("两次填写的新密码不一样");
  131.         }
  132.         //2.调用service完成密码更新
  133.         userService.updatePwd(newPwd);
  134.         //删除redis中对应的token
  135.         ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
  136.         operations.getOperations().delete(token);
  137.         return Result.success();
  138.     }
  139. }
复制代码
4,拦截器里面使用情况:
  1. package com.jinhei.interceptors;
  2. import com.jinhei.utils.JwtUtils;
  3. import com.jinhei.utils.ThreadLocalUtil;
  4. import jakarta.servlet.http.HttpServletRequest;
  5. import jakarta.servlet.http.HttpServletResponse;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.data.redis.core.StringRedisTemplate;
  8. import org.springframework.data.redis.core.ValueOperations;
  9. import org.springframework.stereotype.Component;
  10. import org.springframework.web.servlet.HandlerInterceptor;
  11. import java.util.Map;
  12. @Component
  13. public class LoginInterceptor implements HandlerInterceptor {
  14.     @Autowired
  15.     private StringRedisTemplate stringRedisTemplate;
  16.     @Override
  17.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  18.         //请求头里面拿到令牌,令牌验证
  19.         String token = request.getHeader("Authorization");
  20.         // 验证token
  21.         try {
  22.             //从redis中获取相同的token
  23.             ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
  24.             String redisToken = operations.get(token);
  25.             if (redisToken==null){
  26.                 //token已经失效了
  27.                 throw new RuntimeException(); // 抛出异常,给catch抓捕处理
  28.             }
  29.             Map<String, Object> claims = JwtUtils.parseJWT(token);
  30.             // 把业务数据保存到ThreadLocal中
  31.             ThreadLocalUtil.set(claims);
  32.             // 放行
  33.             return true;
  34.         } catch (Exception e) {
  35.             // HTTP响应码 401
  36.             response.setStatus(401);
  37.             // 不放行
  38.             return false;
  39.         }
  40.     }
  41.     @Override
  42.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  43.        // 移除ThreadLocal中的数据
  44.         ThreadLocalUtil.remove();
  45.     }
  46. }
复制代码





上一篇:37,截取文件名后缀
下一篇:39,SpringBoot项目部署
网站建设,公众号小程序开发,系统定制,软件App开发,技术维护【联系我们】手机/微信:17817817816 QQ:515138

QQ|Archiver|自丢网 ( 粤ICP备2024252464号-1 )

GMT+8, 2026-3-4 08:31

专注于网站建设,公众号小程序制作,商城小程序,系统定制,软件App开发

【联系我们】手机/微信:17817817816 QQ:515138

快速回复 返回顶部 返回列表