How to configure custom security filters to trigger only for specific endpoints in a Spring Boot application with Spring Security?

huangapple go评论61阅读模式
英文:

How to configure custom security filters to trigger only for specific endpoints in a Spring Boot application with Spring Security?

问题

以下是您提供的内容的翻译:

我有一个使用Spring Boot 3和Spring Security 6的应用程序,我很难理解安全过滤器是如何工作的。
我目前有3个公开的端点/endpoint1/endpoint2/endpoint3。我还有两个过滤器Filter1.javaFilter2.java
我想要配置我的安全性,以便仅在调用/endpoint1时触发Filter1,仅在调用/endpoint2时触发Filter2,而对于/endpoint3则不触发任何过滤器。

我得到的结果是,在调用任何端点时,两个过滤器都被触发。

这是我的SecurityFilterChain配置方法:

@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http.csrf()
            .disable()
            .cors()
            .and()
            .authorizeHttpRequests()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
            .permitAll()
            .requestMatchers(new AntPathRequestMatcher("/endpoin3/**"))
            .permitAll()
            .requestMatchers(new AntPathRequestMatcher("/error/**"))
            .permitAll()
            .requestMatchers(new AntPathRequestMatcher("/endpoint1/**"))
            .authenticated()
            .requestMatchers(new AntPathRequestMatcher("/endpoint2/**"))
            .authenticated()
            .anyRequest()
            .denyAll()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilterBefore(
                    new Filter1(),
                    UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(
                    new Filter2(),
                    UsernamePasswordAuthenticationFilter.class)
            .logout()
            .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext());
    return http.build();
}

我尝试了以下方法,但没有任何差异:

@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http.csrf()
            .disable()
            .cors()
            .and()
            .authorizeHttpRequests()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
            .permitAll()
            .requestMatchers(new AntPathRequestMatcher("/endpoin3/**"))
            .permitAll()
            .requestMatchers(new AntPathRequestMatcher("/error/**"))
            .permitAll()
            .and()
            .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers(new AntPathRequestMatcher("/endpoint1/**"))
                    .authenticated()
                    .and()
                    .addFilterBefore(
                            new Filter1(),
                            UsernamePasswordAuthenticationFilter.class))
            .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers(new AntPathRequestMatcher("/endpoint2/**"))
                    .authenticated()
                    .and()
                    .addFilterBefore(
                            new Filter2(),
                            UsernamePasswordAuthenticationFilter.class))
            .authorizeHttpRequests()
            .anyRequest()
            .denyAll()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .logout()
            .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext());
    return http.build();
}

我尝试搜索解决此问题的答案,但只找到了针对Spring Boot 2使用antMatchers()方法的解决方案,但由于Spring Security 6的原因,它在Spring Boot 3中已被弃用。
我还尝试使用@Bean@Order注解在多个SecurityFilterChain上创建多个过滤器,但过滤器停止在所有端点上触发。

请让我知道如果您需要更多的帮助或有其他问题。

英文:

I have a spring boot 3 application with spring security 6. I am having a hard time to understand how security filters work.
I have for the moment 3 exposed endpoint /endpoint1, /endpoint2 and /endpoint3. I also have 2 filters Filter1.java and Filter2.java.
I want to configure my Security in a way that Filter1 only gets triggered when /endpoint1 is called, Filter2 only when /endpoint2 gets called, and for /endpoint3 no filter at all.

The outcome I am getting is that both filters are getting triggered when calling any of the endpoints.

This is my SecurityFilterChain configure method:

@Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.csrf()
                .disable()
                .cors()
                .and()
                .authorizeHttpRequests()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                .permitAll()
                .requestMatchers(new AntPathRequestMatcher("/endpoin3/**"))
                .permitAll()
                .requestMatchers(new AntPathRequestMatcher("/error/**"))
                .permitAll()
                .requestMatchers(new AntPathRequestMatcher("/endpoint1/**"))
                .authenticated()
                .requestMatchers(new AntPathRequestMatcher("/endpoint2/**"))
                .authenticated()
                .anyRequest()
                .denyAll()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(
                        new Filter1(),
                        UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(
                        new Filter2(),
                        UsernamePasswordAuthenticationFilter.class)
                .logout()
                .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext());
        return http.build();
    }

I tried to do the following but it did make any difference:

@Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.csrf()
                .disable()
                .cors()
                .and()
                .authorizeHttpRequests()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                .permitAll()
                .requestMatchers(new AntPathRequestMatcher("/endpoin3/**"))
                .permitAll()
                .requestMatchers(new AntPathRequestMatcher("/error/**"))
                .permitAll()
                .and()
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(new AntPathRequestMatcher("/endpoint1/**"))
                        .authenticated()
                        .and()
                        .addFilterBefore(
                                new Filter1(),
                                UsernamePasswordAuthenticationFilter.class))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(new AntPathRequestMatcher("/endpoint2/**"))
                        .authenticated()
                        .and()
                        .addFilterBefore(
                                new Filter2(),
                                UsernamePasswordAuthenticationFilter.class))
                .authorizeHttpRequests()
                .anyRequest()
                .denyAll()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .logout()
                .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext());
        return http.build();
    }
    }

I have searched to find an answer to my issue but only found found solutions for Spring boot 2 using antMatchers() methods but it is depricated in Spring Boot 3 because of Spring security 6.
I also tried to create multiple SecurityFilterChains with @Bean and @Order annotations on top of them but the filters stoped being triggered on all endpoints.

答案1

得分: 1

这是正确的。antMatchers() 方法已被弃用。您可以尝试创建两个自定义请求匹配器(用于端点1和2)。然后,您可以在两个单独的配置类中(可以自己选择类名),使用这些匹配器来定义每个端点的具体性。这可能有助于触发适用于正确端点的过滤器。

// 自定义请求匹配器用于端点路径
private static final RequestMatcher ENDPOINT_1_MATCHER = new AntPathRequestMatcher("/endpoint1/**");
private static final RequestMatcher ENDPOINT_2_MATCHER = new AntPathRequestMatcher("/endpoint2/**");

// 端点1的配置
@Configuration
public static class Endpoint1SecurityFilter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                .requestMatcher(ENDPOINT_1_MATCHER)
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }
}

// 端点2的配置
@Configuration
public static class Endpoint2SecurityFilter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                .requestMatcher(ENDPOINT_2_MATCHER)
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }
}

PS:对于端点3,我真的不认为需要明确配置过滤器的缺失,因为它不需要任何过滤器。欢迎更好的建议!

英文:

That is true. antMatchers() method is deprecated. Could you try creating two custom request matchers(for endpoint 1 and 2). You can then use those matchers in two separate configuration classes(any class name of choice) where you’d define your specificity for each endpoint. This might help you trigger your filters for the right endpoints.

// Custom request matchers for endpoint paths
private static final RequestMatcher ENDPOINT_1_MATCHER = new AntPathRequestMatcher("/endpoint1/**");
private static final RequestMatcher ENDPOINT_2_MATCHER = new AntPathRequestMatcher("/endpoint2/**");
// Configuration for endpoint 1
@Configuration
public static class Endpoint1SecurityFilter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.requestMatcher(ENDPOINT_1_MATCHER)
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
// endpoint 2 configuration
@Configuration
public static class Endpoint2SecurityFilter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.requestMatcher(ENDPOINT_2_MATCHER)
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
} ```
PS: I  honestly don’t feel it is necessary to explicitly configure the absence of filters for endpoint3 since it doesn’t require any filters.
Open to better suggestions here!
</details>

huangapple
  • 本文由 发表于 2023年5月25日 01:35:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76326112.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定