springSecurityFilterChain如何跳过已登录请求的身份验证

时间:2012-06-27 05:28:02

标签: spring spring-security httpwebrequest

我一直致力于弹簧安全,一切运转良好。但我只是调试它是如何工作的。所有过滤器都通过http命名空间配置为springsecurityfilterchain。其中之一是身份验证过滤器,用于提供身份验我发现当新的登录请求到来时(没有前一个会话)调用了身份验证过滤器,但是当请求来自已登录的用户,即会话存在时,则不会调用authenticationfilter。我无法找到'springsecurity'在已登录的请求中跳过此身份验证的位置和方式。请帮我理解这一点。

由于

5 个答案:

答案 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

组合处理

答案 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。