Browse Source

feat(security): 增加第三方JWT验证日志及Token Redis校验

- 在JwtTokenUtil中添加Token验证各步骤日志输出,便于跟踪验证过程
- 校验Token是否存在于Redis时增加日志,标明Token存在状态
- 在ThirdPartyJwtAuthFilter初始化时输出初始化日志
- 在请求过滤中增加请求URI及Token提取日志,提升调试信息透明度
- 对缺失Token、验证失败及异常情况添加详细错误日志
- 对非第三方接口请求输出调试日志,明确跳过Token验证的原因
SheepHy 1 week ago
parent
commit
4b24a1267e

+ 7 - 1
src/main/java/com/zsElectric/boot/common/util/electric/queryToken/JwtTokenUtil.java

@@ -73,15 +73,19 @@ public class JwtTokenUtil {
      */
     public boolean validateToken(String token) {
         try {
+            log.info("开始验证Token: {}...", token.substring(0, Math.min(20, token.length())));
             // 首先检查Redis中是否存在该token(支持主动撤销)
             if (!isTokenInRedis(token)) {
+                log.error("Token在Redis中不存在,可能已被撤销或过期");
                 return false;
             }
+            log.info("Token在Redis中存在,继续验证JWT签名");
             // 验证JWT签名和过期时间
             Jwts.parserBuilder()
                 .setSigningKey(secretKey)
                 .build()
                 .parseClaimsJws(token);
+            log.info("Token验证通过");
             return true;
         } catch (ExpiredJwtException e) {
             log.error("Token已过期: {}" , e.getMessage());
@@ -134,7 +138,9 @@ public class JwtTokenUtil {
      */
     private boolean isTokenInRedis(String token) {
         String tokenKey = REDIS_TOKEN_PREFIX + token;
-        return Boolean.TRUE.equals(redisTemplate.hasKey(tokenKey));
+        Boolean exists = redisTemplate.hasKey(tokenKey);
+        log.info("检查Token是否在Redis中, key: {}, exists: {}", tokenKey, exists);
+        return Boolean.TRUE.equals(exists);
     }
 
     /**

+ 16 - 0
src/main/java/com/zsElectric/boot/common/util/electric/queryToken/ThirdPartyJwtAuthFilter.java

@@ -5,6 +5,7 @@ import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -19,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+@Slf4j
 @Component
 public class ThirdPartyJwtAuthFilter extends OncePerRequestFilter {
 
@@ -36,31 +38,41 @@ public class ThirdPartyJwtAuthFilter extends OncePerRequestFilter {
             "/dev/v1/linkData/notification_stationStatus"
     );
     private final AntPathMatcher pathMatcher = new AntPathMatcher();
+    
+    public ThirdPartyJwtAuthFilter() {
+        log.warn("========== ThirdPartyJwtAuthFilter 已初始化 ==========");
+    }
 
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
         
         String requestUri = request.getRequestURI();
+        log.info("第三方JWT过滤器处理请求: {}", requestUri);
 
         boolean isThirdPartyRequest = thirdPartyApiPaths.stream()
                 .anyMatch(pattern -> pathMatcher.match(pattern, requestUri));
 
         // 检查当前请求是否是需要第三方Token验证的接口
         if (isThirdPartyRequest) {
+            log.info("检测到第三方接口请求: {}", requestUri);
             String token = extractToken(request);
             
             if (token == null) {
+                log.error("Token缺失,请求URI: {}", requestUri);
                 // Token缺失,通过AuthenticationEntryPoint返回统一错误格式
                 authenticationEntryPoint.commence(request, response, 
                     new AuthenticationServiceException("Missing or invalid Bearer token"));
                 return; // 重要:直接返回,不再执行过滤链后续操作
             }
             
+            log.info("提取到Token: {}...", token.substring(0, Math.min(20, token.length())));
+            
             try {
                 // 验证Token的有效性(例如是否过期、签名是否正确)
                 if (jwtTokenUtil.validateToken(token)) {
                     // 从Token中解析用户标识
                     String principal = jwtTokenUtil.getOperatorIdFromToken(token);
+                    log.info("Token验证成功,OperatorID: {}", principal);
                     // 构建Authentication对象,细节见下文
                     UsernamePasswordAuthenticationToken authentication =
                         new UsernamePasswordAuthenticationToken(principal, null, new ArrayList<>());
@@ -69,16 +81,20 @@ public class ThirdPartyJwtAuthFilter extends OncePerRequestFilter {
                     // 将认证信息设置到SecurityContext中[5](@ref)
                     SecurityContextHolder.getContext().setAuthentication(authentication);
                 } else {
+                    log.error("Token验证失败,Token: {}...", token.substring(0, Math.min(20, token.length())));
                     // Token无效
                     authenticationEntryPoint.commence(request, response, 
                         new AuthenticationServiceException("Invalid token"));
                     return;
                 }
             } catch (Exception e) { // 捕获JWT解析等特定异常
+                log.error("Token验证异常: {}", e.getMessage(), e);
                 authenticationEntryPoint.commence(request, response, 
                     new AuthenticationServiceException("Token validation failed: " + e.getMessage()));
                 return;
             }
+        } else {
+            log.debug("非第三方接口请求,跳过Token验证: {}", requestUri);
         }
         
         // 如果不是第三方接口,或者Token验证通过,则继续执行后续过滤器