diff --git a/datasophon-api/src/main/java/com/datasophon/api/interceptor/CsrfTokenInterceptor.java b/datasophon-api/src/main/java/com/datasophon/api/interceptor/CsrfTokenInterceptor.java index 74b516c1..b3421bd5 100644 --- a/datasophon-api/src/main/java/com/datasophon/api/interceptor/CsrfTokenInterceptor.java +++ b/datasophon-api/src/main/java/com/datasophon/api/interceptor/CsrfTokenInterceptor.java @@ -23,35 +23,35 @@ @Component public class CsrfTokenInterceptor implements HandlerInterceptor { - + private static final Logger logger = LoggerFactory.getLogger(CsrfTokenInterceptor.class); - + private static final ConcurrentHashMap CSRF_TOKEN_STORE = new ConcurrentHashMap<>(); - + private static final Set SAFE_METHODS = new HashSet<>(Arrays.asList("GET", "HEAD", "OPTIONS")); - + public static String generateToken(String sessionId) { String token = UUID.randomUUID().toString().replace("-", ""); CSRF_TOKEN_STORE.put(sessionId, token); return token; } - + public static void removeToken(String sessionId) { CSRF_TOKEN_STORE.remove(sessionId); } - + @Override public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { if (SAFE_METHODS.contains(request.getMethod())) { return true; } - + // API token auth is inherently CSRF-safe (browser won't auto-attach custom headers) String apiToken = request.getHeader("token"); if (StringUtils.isNotBlank(apiToken)) { return true; } - + String sessionId = request.getHeader(Constants.SESSION_ID); if (StringUtils.isBlank(sessionId)) { Cookie cookie = WebUtils.getCookie(request, Constants.SESSION_ID); @@ -60,25 +60,23 @@ public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServl } } if (StringUtils.isBlank(sessionId)) { - logger.warn("CSRF check failed: missing sessionId"); - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - return false; - } - - String clientToken = request.getHeader(Constants.CSRF_HEADER); - if (StringUtils.isBlank(clientToken)) { - logger.warn("CSRF check failed: missing {} header", Constants.CSRF_HEADER); - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - return false; + // 未登录用户,无需 CSRF 防护 + return true; } - + String serverToken = CSRF_TOKEN_STORE.get(sessionId); - if (serverToken == null || !serverToken.equals(clientToken)) { + if (serverToken == null) { + // 内存中无 CSRF token(服务重启后旧 session),放行由 LoginInterceptor 判断 session 有效性 + return true; + } + + String clientToken = request.getHeader(Constants.CSRF_HEADER); + if (StringUtils.isBlank(clientToken) || !serverToken.equals(clientToken)) { logger.warn("CSRF check failed: token mismatch for session {}", sessionId); - response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.setStatus(javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED); return false; } - + return true; } }