Spring 引导 HTTP 安全配置匿名过滤器和不同路径上的自定义过滤器

Spring Boot HTTP security configuration anonymous filter and a custom filter on a different path

我在尝试使用 WebSecurityConfigurerAdapter 配置 HTTP 安全性时遇到了一个奇怪的问题。这是完整的配置 class 目前为止我试过:

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@ConditionalOnProperty(name = "module.client.security.enabled")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Value("${management.endpoints.web.base-path}")
  private String managementEndpoint;

  @Autowired
  private List<ModuleProperties> moduleProperties;

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

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().disable();
    http.formLogin().disable();
    // FIXME also doesn't work because of the later http.requestMatchers().antMatchers() calls
    http.authorizeRequests()
        .antMatchers("/**").anonymous();

    http.requestMatchers()
        .antMatchers("/app/**")
        .and()
        .addFilterBefore(new ClientResolveFilter(), FilterSecurityInterceptor.class);

  }

我想做的实际上是为所有端点启用匿名身份验证 — 以防止在 SecurityContextHolder 上操作时出现 NullPointerException — 另外, enabling/adding 自定义过滤器仅针对一个子集或不同的端点路径,在这种情况下为 /app/**

我预计上面的代码会起作用,但实际发生的是 AnonymousAuthenticationFilter 对所有人禁用,并且两个过滤器仅适用于路径 /app/**

如果我删除了 http.requestMatchers().antMatchers("/app/**") 部分,那么 AnonymousAuthenticationFilter 将照常适用于所有路径。我怀疑第二个 .antMatchers("/app/**") 调用有点取代前一个或隐式替换它,这对我来说没有意义,但我可能是错的。

我尝试深入研究源代码,但仍然感到困惑,无法找到一个干净的解决方案来使其按我的预期工作。任何想法和帮助将不胜感激。

干杯!

编辑:我正在使用 Spring Boot 2.5.2,Spring 安全版本是 5.5.1

addFilterBefore(和其他 addFilter*)方法会将过滤器添加到适用于所有请求的过滤器链中。如果您希望过滤器仅适用于某些请求,则必须检查过滤器内部(例如,使用 HttpServletRequest.getgetRequestURI() 检查 url)。

在@Dickson 的建议下,我找到了一个由 spring boot 提供的名为 FilterRegistrationBean 的特殊 bean。

因此,我将其配置为一个 bean,它仅将特定的 servlet 过滤器应用于已配置的路径:

@Bean
public FilterRegistrationBean<ClientResolveFilter> clientResolveFilter(){
  final FilterRegistrationBean<ClientResolveFilter> frb = new FilterRegistrationBean<>();
  frb.setFilter(new ClientResolveFilter());
  frb.addUrlPatterns("/app/*");
  return frb;
}

这个解决方案非常适合我的要求。

注意路径字符串现在不是蚂蚁匹配器——必须写成单/app/*而不是双/app/**——它实际上是我们像过去一样手动配置 web.xml 文件时的模式:)