我认为 SessionManagementFilter 可以解决这个问题:
if (!securityContextRepository.containsContext(request)) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && !authenticationTrustResolver.isAnonymous(authentication)) {
// The user has been authenticated during the current request, so call the session strategy
try {
sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
} catch (SessionAuthenticationException e) {
// The session strategy can reject the authentication
logger.debug("SessionAuthenticationStrategy rejected the authentication object", e);
SecurityContextHolder.clearContext();
failureHandler.onAuthenticationFailure(request, response, e);
return;
}
// Eagerly save the security context to make it available for any possible re-entrant
// requests which may occur before the current request completes. SEC-1396.
securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
} else {
// No security context or authentication present. Check for a session timeout
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
if(logger.isDebugEnabled()) {
logger.debug("Requested session ID " + request.getRequestedSessionId() + " is invalid.");
}
if (invalidSessionStrategy != null) {
invalidSessionStrategy.onInvalidSessionDetected(request, response);
return;
}
}
}
}
当然,这里还有更多的东西。身份验证存储在 ThreadLocal 中:
在 Spring Security 中,存储请求之间的 SecurityContext 的责任落在了 SecurityContextPersistenceFilter 上,它默认将上下文存储为 HTTP 请求之间的 HttpSession 属性。它为每个请求将上下文恢复到 SecurityContextHolder,并且至关重要的是,在请求完成时清除 SecurityContextHolder。出于安全目的,您不应直接与 HttpSession 交互。这样做根本没有理由 - 始终使用 SecurityContextHolder 代替。
因此,SecurityContextPersistenceFilter 负责加载上下文数据(并稍后将其删除),过滤器链中的其他模块将根据这些数据做出决策。(例如跳过或通过 usermanager 服务进行身份验证)
我不是 SpringSecurity 开发人员,因此仅将此信息作为有根据的猜测:)