【问题标题】:Why does Spring call an aditional filter chain as well as an original filter chain?为什么 Spring 调用一个额外的过滤器链以及一个原始的过滤器链?
【发布时间】:2021-05-01 03:51:53
【问题描述】:

在我的日志中,我发现 Spring 在授权我的请求时调用了两个单独的过滤器链。所以我的问题是,为什么 Spring 调用 additional 过滤器链以及 original 过滤器链。因为这种行为会导致我的应用程序在处理请求时对用户进行两次身份验证。特别是它不必要地再次调用我的 AuthenticationFilter。

在这里你可以看到日志:

27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/api/account/@me'; against '/api/account/**'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 1 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 4 of 10 in additional filter chain; firing Filter: 'TokenAuthenticationFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] d.t.o.a.a.TokenAuthenticationFilter      : Request is to process authentication
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using dev.teamnight.oauth2.authserver.authentication.ApplicationAuthenticationProvider
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using dev.teamnight.oauth2.authserver.authentication.BearerAuthenticationProvider
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] d.t.o.a.a.TokenAuthenticationFilter      : Authentication success. Updating SecurityContextHolder to contain: dev.teamnight.oauth2.authserver.authentication.TokenAuthenticationToken@aeed7374: Principal: dev.teamnight.oauth2.authserver.authentication.OAuth2Principal@46a2793d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'dev.teamnight.oauth2.authserver.authentication.TokenAuthenticationToken@aeed7374: Principal: dev.teamnight.oauth2.authserver.authentication.OAuth2Principal@46a2793d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@5f8a02cf
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request '/api/account/@me' matched by universal pattern '/**'
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /api/account/@me; Attributes: [hasAnyAuthority('READ_ALL','BEARER_ACCESS')]
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: dev.teamnight.oauth2.authserver.authentication.TokenAuthenticationToken@aeed7374: Principal: dev.teamnight.oauth2.authserver.authentication.OAuth2Principal@46a2793d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.h.RoleHierarchyImpl              : getReachableGrantedAuthorities() - From the roles [SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS] one can reach [SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS] in zero or more steps.
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2830c7a3, returned: 1
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
<< Additional Filter Chain Ends >> 27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : /api/account/@me reached end of additional filter chain; proceeding with original chain
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] d.t.o.a.a.TokenAuthenticationFilter      : Request is to process authentication
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using dev.teamnight.oauth2.authserver.authentication.ApplicationAuthenticationProvider
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using dev.teamnight.oauth2.authserver.authentication.BearerAuthenticationProvider
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] d.t.o.a.a.TokenAuthenticationFilter      : Authentication success. Updating SecurityContextHolder to contain: dev.teamnight.oauth2.authserver.authentication.TokenAuthenticationToken@c97cfb62: Principal: dev.teamnight.oauth2.authserver.authentication.OAuth2Principal@571022e9; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor    : Secure object: ReflectiveMethodInvocation: public dev.teamnight.oauth2.authserver.entities.json.AccountDTO dev.teamnight.oauth2.authserver.controllers.ApiController.getBearedAccount(javax.servlet.http.HttpServletRequest); target is of class [dev.teamnight.oauth2.authserver.controllers.ApiController]; Attributes: [[authorize: 'hasAuthority('BEARER_ACCESS')', filter: 'null', filterTarget: 'null']]
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor    : Previously Authenticated: dev.teamnight.oauth2.authserver.authentication.TokenAuthenticationToken@c97cfb62: Principal: dev.teamnight.oauth2.authserver.authentication.OAuth2Principal@571022e9; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.h.RoleHierarchyImpl              : getReachableGrantedAuthorities() - From the roles [SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS] one can reach [SCOPE_account.email, BEARER_ACCOUNT_1, SCOPE_account.basic, BEARER_ACCESS] in zero or more steps.
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@35948508, returned: 1
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor    : Authorization successful
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor    : RunAsManager did not change Authentication object
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@37c5e3bd
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
27-01-2021 DEBUG 10784 --- [nio-8080-exec-3] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

这是我的网络安全配置:

        @Bean
        @Qualifier("accountApiAuthenticationFilter")
        public TokenAuthenticationFilter accountApiAuthenticationFilter(TokenAuthenticationFailureHandler failureHandler,
                TokenAuthenticationSuccessHandler successHandler) throws Exception {
            TokenAuthenticationFilter filter = new TokenAuthenticationFilter();
            filter.setAuthenticationManager(authenticationManagerBean());
            filter.setAuthenticationFailureHandler(failureHandler);
            filter.setAuthenticationSuccessHandler(successHandler);
            filter.setAllowedTokenTypes(TokenType.APPLICATION, TokenType.BEARER);
            return filter;
        }
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/account/**")
                .addFilterBefore(accountApiAuthenticationFilter(null, null), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("**").hasAnyAuthority("READ_ALL", "BEARER_ACCESS")
                .anyRequest().authenticated()
                .and()
                .authenticationProvider(this.appProvider)
                .authenticationProvider(this.bearerProvider)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(new TokenAuthenticationEntryPoint())
                .and()
                .cors().disable()
                .formLogin().disable()
                .csrf().disable()
                .logout().disable();
        }

【问题讨论】:

  • 因为您将TokenAuthenticationFilter 添加为Filter。默认情况下,上下文中的任何注册过滤器都将添加到常规过滤器链中。您正在将其再次添加到安全链中。您应该添加一个FilterRegistrationBean,它会为常规过滤器链禁用此过滤器的注册。
  • @M. Deinum 我该怎么做,因为我有多个配置有两个单独的 TokenAuthenticationFilter?
  • 为每个添加一个。
  • @M.Deinum 它现在确实有效,如果需要,您可以将其发布为答案,因此我可以将其标记为解决方案。

标签: java spring spring-boot authentication spring-security


【解决方案1】:

默认情况下,Spring Boot 将在常规 FilterChain 中注册所有 javax.servlet.Filter 实例。您可以通过添加 FilterRegistrationBean(来自 Spring Boot)来禁用此注册来影响这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2015-05-08
    • 2018-12-13
    • 2014-12-19
    • 1970-01-01
    • 2012-10-27
    相关资源
    最近更新 更多