1

我一直在从事 spring security 工作,一切都运行良好。但我只是去调试它是如何工作的。所有过滤器都通过 http 命名空间为 springsecurityfilterchain 配置。其中之一是用于提供身份验证的身份验证过滤器。我发现当一个新的登录请求到来时(没有以前的会话),身份验证过滤器被调用,但是当请求来自已经登录的用户时,即一个会话存在,那么身份验证过滤器不会被调用。我找不到“springsecurity”在哪里以及如何跳过已登录请求的此身份验证。请帮助我理解这一点。

谢谢

4

5 回答 5

0

它是由三个组合处理的Filters

于 2012-07-05T00:54:57.833 回答
0

httpSessionIntegrationFilter照顾这个。它负责维护来自同一用户的请求之间的会话。

于 2012-07-12T10:01:38.023 回答
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 开发人员,因此仅将此信息作为有根据的猜测:)

于 2012-06-27T09:26:18.130 回答
0

当向安全对象发出请求时,SessionManagementFilter 将查看 SecurityContextRepository。如果其内容与 SecurityContextHolder 匹配,则假定该用户之前已通过身份验证(如记住我或预身份验证)。

如果存储库包含安全上下文,则此过滤器不执行任何操作。

如果它什么都没有并且 ThreadLocal 包含一个身份验证对象,则它假定以前的过滤器已经以某种方式对该用户进行了身份验证。

于 2012-07-09T08:03:02.407 回答
0

好的问题可能仍然是实际的,因此将尝试回答:

根据我自己的研究,它看起来不像“跳过”。

首先 spring 生成过滤器链。如果您使用弹簧启动 - 只需启用调试并在启动日志中您可以看到整个过滤器链。

每个请求都通过这个链——不管你在“configure”方法和 HttpSecurity 对象中配置了什么。所以你的短语

我发现当一个新的登录请求到来时(没有以前的会话),身份验证过滤器被调用,但是当请求已经登录用户时,即一个会话存在,那么身份验证过滤器不会被调用

不是真的。将调用身份验证过滤器,但在 doFilter 内部存在检查请求,如果 URL 不用于登录 - 过滤器调用 doFilter 并“返回”。示例:您将 LoginPage 过滤器配置为“/login POST”。您可以使用不同的凭据将 POST 请求一一发送到 /login,您的应用程序会将会话重写给新用户。因此,如果您不想让用户这样做 - 您可以覆盖过滤器和一些逻辑来检查用户是否登录并调用 doFilter。

于 2018-05-14T16:00:00.153 回答