david 2 лет назад
Родитель
Сommit
18716a678e

+ 19 - 25
src/main/java/com/roma/romaapi/interceptor/JWTInterceptor.java

@@ -11,6 +11,9 @@ import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.HandlerInterceptor;
 
+import static com.roma.romaapi.utils.JWTUtil.REDIS_USER_EXPIRE_TIME;
+import static com.roma.romaapi.utils.JWTUtil.SIGN;
+
 /***
  这个拦截器就是调用了工具类中验证Token的部分 对前端用户传回的Token是否合法 以及是否保存了UID等信息进行验证
  验证通过就放行
@@ -30,47 +33,38 @@ public class JWTInterceptor implements HandlerInterceptor {
 
     @Override
     public boolean preHandle(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler) throws Exception {
-        // 从Header中获得Token 和 uid 这两个是要与前端同步的
-
+        // 从Header中获得Token
         String token = request.getHeader("token");
-        String uid = request.getHeader("uid");
-
         if(token==null || token.equals("")){
             throw new Exception("Header 未装载 token");
         }
-
-        if(uid==null ||  uid.equals("")){
-            throw new Exception("Header 未装载 uid");
-        }
-
         try {
-
             // 得到签名实体
-            DecodedJWT verify = jwtUtil.verify(token, Long.valueOf(uid));
+            DecodedJWT verify = jwtUtil.verify(token);
 
             // 得到签名中的登录时间
             String loginTimeFromToken = verify.getClaim("userLoginTime").asString();
 
             System.out.println("token-----"+loginTimeFromToken);
-            log.info("token:" + loginTimeFromToken);
-
-            // 从Redis中获取用户的信息
-//            User user = redisUtil.getObject(RedisPrefix.USER + uid, User.class);
-
-//            String loginTimeFromRedis = BaseUtil.localDateTime2String(user.getuLoginTime());
-
-//            log.info("redis:" + loginTimeFromRedis);
-
-//            if (!loginTimeFromRedis.equals(loginTimeFromToken)){
-//                throw new Exception("用户Token已更新");
-//            }
 
         } catch (SignatureVerificationException e) {
 
             throw new Exception("无效Token签名");
         } catch (TokenExpiredException e) {
-
-            throw new Exception("token过期");
+            /*若抛出token过期异常,检查redis中的是否存在token以及请求头中的token与redis中的token是否相同
+            如果相同,说明用户仍在操作,只是请求头中的token已经过期,此时需要对token进行续期*/
+            // 从Redis中获取缓存中的token,判断是否过期
+            String userId = stringRedisTemplate.opsForValue().get(SIGN + token);
+            if(null == userId || userId.equals("")){
+                throw new Exception("Original Token 无效或已过期");
+            } else {
+                // 续期
+                String redisTokenKey = SIGN + token;
+                stringRedisTemplate.opsForValue().set(redisTokenKey, userId, REDIS_USER_EXPIRE_TIME);
+
+                return true;
+            }
+//            throw new Exception("token过期");
         } catch (AlgorithmMismatchException e) {
 
             throw new Exception("token算法不一致");

+ 19 - 15
src/main/java/com/roma/romaapi/utils/JWTUtil.java

@@ -32,6 +32,9 @@ public class JWTUtil {
     // 加盐
     private static final String SECRET = "rd!rew231sods4df?m2wsa";
 
+    // redis用户token缓存时间,单位秒
+    public static final int REDIS_USER_EXPIRE_TIME = 1800;
+
     @Autowired
     StringRedisTemplate stringRedisTemplate;
 
@@ -48,34 +51,35 @@ public class JWTUtil {
         instance.add(Calendar.DATE, 7);
 
         JWTCreator.Builder builder = JWT.create();
-
-        builder.withClaim("userId", String.valueOf(userMapInfo.get("id")))
+        String userId = String.valueOf(userMapInfo.get("id"));
+        builder.withClaim("userId", userId)
                 .withClaim("userLoginTime", String.valueOf(userMapInfo.get("loginTime")))
                 .withClaim("userName", String.valueOf(userMapInfo.get("name")))
                 .withClaim("expTime", simpleDateFormat.format(new Date(instance.getTime().getTime())));
+        String jwtToken = builder.withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256(SIGN + SECRET + userId));
+        // 将缓存的信息添加到redis中
+        String redisTokenKey = SIGN + jwtToken;
+        stringRedisTemplate.opsForValue().set(redisTokenKey, userId, REDIS_USER_EXPIRE_TIME);
 
-        // 将 用户ID + 用户密码 用MD5 混淆 再加盐 获取的字符串 用来生成签名
-        return builder.withExpiresAt(instance.getTime())
-                .sign(Algorithm.HMAC256(String.valueOf(userMapInfo.get("id")) + SECRET));
+        return jwtToken;
     }
 
     /**
      * 验证token合法性 成功返回token
      */
-    public DecodedJWT verify(String token, Long uId) throws Exception {
-
-        // 从Redis中获取用户ID + 密码 并被MD5 混淆后的字符串
-        String strSign = stringRedisTemplate.opsForValue().get(SIGN + uId);
-
-        if(null == strSign){
-            throw new Exception("Original Token 无效或已过期");
+    public DecodedJWT verify(String token) throws Exception {
+        if(token.equals("")){
+            throw new Exception("token不能为空");
         }
+        // 从Redis中获取缓存中的token,判断是否过期
+        String userId = stringRedisTemplate.opsForValue().get(SIGN + token);
 
-        if(token==null || token.equals("")){
-            throw new Exception("token不能为空");
+        if(null == userId || userId.equals("")){
+            throw new Exception("Original Token 无效或已过期");
         }
 
-        JWTVerifier build = JWT.require(Algorithm.HMAC256(strSign + SECRET)).build();
+        JWTVerifier build = JWT.require(Algorithm.HMAC256(SIGN + SECRET + userId)).build();
 
         return build.verify(token);
     }