我一直致力于弹簧安全,一切运转良好。但我只是调试它是如何工作的。所有过滤器都通过http命名空间配置为springsecurityfilterchain。其中之一是身份验证过滤器,用于提供身份验我发现当新的登录请求到来时(没有前一个会话)调用了身份验证过滤器,但是当请求来自已登录的用户,即会话存在时,则不会调用authenticationfilter。我无法找到'springsecurity'在已登录的请求中跳过此身份验证的位置和方式。请帮我理解这一点。
由于
答案 0 :(得分:0)
我认为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开发人员,因此请将此信息仅作为有根据的猜测:)
答案 1 :(得分:0)
由三个Filters
:
SecurityContextPersistenceFilter
的 Authentication
从会话(如果它存在)并将其放在线程本地SecurityContextHolder
中,以便其他过滤器可以看到它。
如果SecurityContextHolder
中没有Authentication
,则AnonymousAuthenticationFilter
会向SecurityContextHolder
添加AnonymousAuthenticationToken
。
FilterSecurityInterceptor
抛出
如果Authentication
中的SecurityContextHolder
没有正确的,则会出现例外情况
当前请求的权限(例如ROLE_USER
)。
答案 2 :(得分:0)
当向安全对象发出请求时,SessionManagementFilter将查看SecurityContextRepository。如果其内容与SecurityContextHolder匹配,则假定该用户之前已经过身份验证(如记住我或预身份验证)。
如果存储库包含安全上下文,则此过滤器不执行任何操作
如果它没有任何内容并且ThreadLocal包含一个Authentication Object,它会假定先前的过滤器以某种方式验证了该用户。
答案 3 :(得分:0)
httpSessionIntegrationFilter
会解决这个问题。它负责维护来自同一用户的请求之间的会话。
答案 4 :(得分:0)
好的问题仍然可以实际,所以会尝试回答:
从我自己的研究来看,它看起来并不像跳过"。
首先,spring生成过滤链。如果你使用spring boot - 只需启用debug并在启动日志中就可以看到整个过滤器链。
每个请求都通过这个链 - 并不重要你配置的"配置"方法和HttpSecurity对象。所以你的短语
我发现当新的登录请求到来时(之前的会话没有)调用身份验证过滤器,但是当请求来自已登录的用户,即会话存在时,则不会调用authenticationfilter
不是真的。将调用身份验证过滤器,但在doFilter内部存在检查请求,如果URL不是登录 - 过滤器调用doFilter和"返回"。 例: 您将LoginPage过滤器配置为" / login POST"。您可以使用不同的凭据逐个发送POST请求到/ login,您的应用程序会将会话重写为新用户。因此,如果您不想让用户这样做 - 您可以覆盖过滤器和一些逻辑来检查会话,如果用户登录并只是调用doFilter。