go to index

spring boot 3.x 根据URL前缀添加不同过滤器的解决方法

read time 2 min read
Spring Boot URL 过滤器

简介

在 Spring Boot 3.x 中,根据不同的 URL 前缀添加不同的过滤器可以通过多种方式实现。本文介绍了三种方案,最终第三种方案被证明是有效的。

方案一:使用 securityMatcher 匹配

通过 securityMatcher 方法为不同的 URL 前缀添加过滤器:

java
http.securityMatcher("/api/**")
    .addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);

http.securityMatcher("/openapi/**")
    .addFilterBefore(openApiAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

这种方法在某些情况下可能无法正确工作,因为多个 securityMatcher 可能会相互干扰。

方案二:定义不同的 SecurityFilterChain

通过定义多个 SecurityFilterChain 来为不同的 URL 前缀配置安全策略和过滤器:

java
@Bean
@Order(1)
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.disable())
        .securityMatcher("/api/**")
        .authorizeHttpRequests(authorize -> authorize
            .requestMatchers("/api/auth/**", "/api/user/create").permitAll()
            .anyRequest().authenticated()
        )
        .exceptionHandling(exception -> exception
            .authenticationEntryPoint(authenticationEntryPoint)
        )
        .sessionManagement(session -> session
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        )
        .addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

@Bean
@Order(2)
public SecurityFilterChain openApiSecurityFilterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.disable())
        .securityMatcher("/openapi/**")
        .authorizeHttpRequests(authorize -> authorize
            .requestMatchers("/openapi/**").permitAll()
            .anyRequest().authenticated()
        )
        .exceptionHandling(exception -> exception
            .authenticationEntryPoint(authenticationEntryPoint)
        )
        .sessionManagement(session -> session
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        )
        .addFilterBefore(openApiAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

这种方法通过定义多个 SecurityFilterChain 来确保每个 URL 前缀有独立的安全配置,避免了冲突。

方案三:重写 shouldNotFilter 方法

通过在过滤器中重写 shouldNotFilter 方法来控制过滤器的应用范围:

java
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
    String path = request.getRequestURI();
    return path.startsWith("/openapi/");
}

这种方式简单且有效,适用于需要针对特定路径禁用过滤器的场景。

最终选择

经过测试,方案三是最有效的解决方案。它通过简单的条件判断实现了对不同 URL 前缀的过滤器应用,避免了复杂的配置和潜在的冲突问题。