【问题标题】:Spring Security add filter to all Endpoint EXCEPT oneSpring Security 向所有端点添加过滤器,除了一个
【发布时间】:2019-02-01 23:54:47
【问题描述】:

我对此进行了研究,并在 SO 上找到了这个 Answer

不过,我确实对这个问题提出了补充问题:

我有一组过滤器,我想将其应用于所有请求,除了特殊情况(例如:除 /mgmt/** 和 /error/** 之外的所有路径)。

这不能使用链接答案中提供的相同方法来完成,因为我会将过滤器添加到默认的 http-security 对象,然后它也适用于特殊情况。

有没有像“否定匹配器”这样的东西,让我可以做这样的事情:

http.negativeAntMatchers("/mgmt/**).addFilter(...)

为除 /mgmt/** 之外的所有内容添加过滤器?

我的代码:

这是“/mgmt”的配置,将 ManagementBasicAuthFilter 放在链中 - 这是有效的,因为除了“/mgmt/**”之外没有端点要求基本身份验证。

@Order(1)
@Configuration
@RequiredArgsConstructor
public static class ManagementSecurityConfig extends WebSecurityConfigurerAdapter {

    private final AuthenticationManager authenticationManager;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("mgmt/**")
                .csrf().disable()
                .headers().frameOptions().sameOrigin()
                .cacheControl().disable()
                .and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .addFilterBefore(new ManagementBasicAuthenticationFilter(authenticationManager,
                        getAuthenticationEntryPoint(), "/mgmt"), BasicAuthenticationFilter.class)
                    .authorizeRequests()
                    .anyRequest()
                    .permitAll();
    }

    private BasicAuthenticationEntryPoint getAuthenticationEntryPoint() {
        BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
        entryPoint.setRealmName("myApp");
        return entryPoint;
    }
}

这是所有入口点的配置,除了 mgmt - 此文件中的所有过滤器都不应应用于 /mgmt/**

@Order(2)
@Configuration
@RequiredArgsConstructor
@Import({ ResourceServerTokenServicesConfiguration.class })
@EnableOAuth2Client
public static class OAuthSecurityConfig extends WebSecurityConfigurerAdapter {

    private final OAuth2ClientContextFilter clientContextFilter;
    private final OAuth2ClientAuthenticationProcessingFilter ssoFilter;
    private final StatePropagatingLoginRedirectFilter statePropagatingLoginRedirectFilter;


    @Override
    public void configure(WebSecurity web) {
      web.ignoring().antMatchers("/mgmt/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .headers().frameOptions().sameOrigin()
                .cacheControl().disable()
                .and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .exceptionHandling()
                        .defaultAuthenticationEntryPointFor(
                            new LoginUrlAuthenticationEntryPoint("/login"),
                            request -> true)
                .and()
                .addFilterAfter(statePropagatingLoginRedirectFilter, AbstractPreAuthenticatedProcessingFilter.class)
                .addFilterAfter(ssoFilter, statePropagatingLoginRedirectFilter.getClass())
                .addFilterAfter(clientContextFilter, ssoFilter.getClass())
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }
}

当我请求例如:“/mgmt/health”时,系统会提示我进行基本身份验证,但登录后,(statePropagating、sso、clientContext)中的过滤器仍然会被应用 - 这是为什么呢?

【问题讨论】:

    标签: spring spring-boot spring-security


    【解决方案1】:

    感谢 kimhom 和他的 answer 以及 Nicholas 和 eg78 我想通了 - web.ignoring 不起作用,原因我想稍后再调查 - 我忘记的是,那个 spring 会自动添加所有过滤器作为 Bean 出现在所有过滤器链中。为了防止这种情况,人们可以

    1. 不将过滤器注册为 bean 并手动实例化它们 他们是需要的
    2. 为过滤器添加一个FilterRegistrationBean 像这样提问并禁用他们的注册:

      @Bean
      public FilterRegistrationBean disableMyFilterBean(MyFilterBean filter) {
          FilterRegistrationBean registration = new FilterRegistrationBean(filter);
          registration.setEnabled(false);
          return registration;
      }
      

    然后我的过滤器只应用于我想要它们的地方 - 我什至不需要提供WebSecurity.ignoring匹配器

    【讨论】:

      【解决方案2】:

      您可以使用 web.ignoring 配置 spring security 以忽略某些 url 模式 你的情况

      web.ignoring().antMatchers("/mgmt/**");
      

      【讨论】:

      • web 是 WebSecurity 配置项。无论如何,尼古拉斯 K 写了一个更好的答案。
      【解决方案3】:

      如果我正确理解您的问题,您不希望将过滤器应用于/mgmt,那么您可以使用

          @Configuration
          @EnableWebSecurity
          public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
             @Override
             public void configure(WebSecurity web) {
                // Overridden to exclude some url's 
                web.ignoring().antMatchers("/mgmt");
             }
      
      
             @Override
             protected void configure(HttpSecurity http) throws Exception {
              // configure the other url's as required
             }
      
          }
      

      【讨论】:

      • 谢谢,我会试试这个 - 到目前为止我只使用了 HttpSecurity-config
      • 好的,我登录时没有意识到它何时起作用,所以我接受了答案,而实际上问题没有解决,我将在问题中添加详细信息
      • 这是完全相同的问题,我只是添加了代码,因为您的答案没有解决问题,我想,最可能需要更多信息
      • 我通过搜索您的答案不能解决问题的情况来解决这个问题 - 所以我想在应得的地方给予信任,而不是仅仅接受我自己的答案,就好像我想通了我自己的
      【解决方案4】:

      您需要允许“/mgmt/**”中的所有请求,并使其他请求经过身份验证,尝试类似的方法。

          http    
              .authorizeRequests()
                      .antMatchers("**").hasAnyAuthority("ANY_AUTHORITY")
                      .antMatchers("/mgmt/**").permitAll()
                      .anyRequest().authenticated()
      

      【讨论】:

        猜你喜欢
        • 2018-09-14
        • 2017-11-22
        • 1970-01-01
        • 1970-01-01
        • 2019-04-13
        • 1970-01-01
        • 2014-09-04
        • 2014-12-23
        • 2019-10-01
        相关资源
        最近更新 更多