Spring Security add filter to all Endpoint EXCEPT one

被刻印的时光 ゝ 提交于 2021-02-08 05:18:40

问题


I researched this and found this Answer on SO.

I do however have the complementary question to this one:

I have a set of filters, that i want to be applied to ALL requests, EXCEPT special cases (eg.: all paths except /mgmt/** and /error/**).

This cannot be done using the same method presented in the linked answer, as I would add the filters to the default http-security Object, which would then apply for the special cases too.

is there a thing like "negative matchers", allowing me to do something like:

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

to add a filter for everything except /mgmt/** ?

my code:

This is the config for "/mgmt", placing the ManagementBasicAuthFilter in the chain - this works, as no endpoints except "/mgmt/**" ask for basic auth.

@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;
    }
}

This is the config for all entrypoints, EXCEPT mgmt - all filters in this file should NOT apply to /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();
    }
}

When i Request eg.: "/mgmt/health", i get prompted for basic auth, but after login, the filters in the (statePropagating, sso, clientContext) still get applied - why is this?


回答1:


If I understand your question right, you don't want a filter to be applied to /mgmt then you could use

    @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
       }

    }



回答2:


thanks to kimhom and his answer in combination with Nicholas and e.g.78 i figured it out - web.ignoring does not work, for reasons i want to investigate later - what i forgot about is, that spring will automatically add all filters present as Beans to all filter chains. to prevent this, one can either

  1. not register filters as beans and instantiate them manually where they are needed
  2. add a FilterRegistrationBean for the filters in question and disable registration for them like this:

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

Then my filters are only applied where i want them to - i do not even need to provide WebSecurity.ignoring matchers




回答3:


You can configure spring security to ignore some url patterns using web.ignoring In your case

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



回答4:


You'll need to permit all requests in "/mgmt/**" and make other requests authenticated, try something like that.

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


来源:https://stackoverflow.com/questions/52039388/spring-security-add-filter-to-all-endpoint-except-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!