spring-boot 中的过滤顺序

新手上路,请多包涵

如何在 spring-boot 中指定过滤器的顺序?我需要在 Spring Security 过滤器之后插入我的 MDC 过滤器。我几乎尝试了所有方法,但我的过滤器始终是第一位的。这没有用:

 @Bean
@Order(Ordered.LOWEST_PRECEDENCE)
public UserInsertingMdcFilter userInsertingMdcFilter() {
    return new UserInsertingMdcFilter();
}

这也不起作用:

 @Bean
public FilterRegistrationBean userInsertingMdcFilterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    UserInsertingMdcFilter userFilter = new UserInsertingMdcFilter();
    registrationBean.setFilter(userFilter);
    registrationBean.setOrder(Integer.MAX_VALUE);
    return registrationBean;
}

原文由 igo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 928
2 个回答

来自 Spring 的家伙再次提供帮助。请参阅 https://github.com/spring-projects/spring-boot/issues/1640https://jira.spring.io/browse/SEC-2730

Spring Security 不会在它创建的 Filter bean 上设置顺序。这意味着,当 Boot 为其创建 FilterRegistrationBean 时,它获得默认顺序 LOWEST_PRECEDENCE。

如果您希望自己的过滤器在 Spring Security 之后运行,您可以为 Spring Security 的过滤器创建自己的注册并指定顺序。

所以我的问题的答案是:

 @Bean
public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
    registration.setOrder(Integer.MAX_VALUE - 1);
    registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
    return registration;
}

@Bean
public FilterRegistrationBean userInsertingMdcFilterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    UserInsertingMdcFilter userFilter = new UserInsertingMdcFilter();
    registrationBean.setFilter(userFilter);
    registrationBean.setOrder(Integer.MAX_VALUE);
    return registrationBean;
}

原文由 igo 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是一个与 Spring Boot 2 / Spring Security 5 兼容的答案,它允许您将过滤器插入过滤器链中的任意位置。

我的用例是自定义日志记录 javax.servlet.Filter 我想在任何 Spring Security 过滤器之前执行;然而,下面的步骤应该允许你在现有的 Spring 过滤器链中的任何地方放置一个过滤器:

第 1 步:找出现有设置中 Spring 过滤器的顺序。

将您最喜欢的远程调试器连接到您的应用程序,并在 --- 的 org.springframework.security.web.FilterChainProxy doFilter(ServletRequest request, ServletResponse response) 方法中设置断点。从 Spring Security 5.1.6 开始,即第 311 行。在调试器中,通过检查 this.additionalFilters 找出现有过滤器。在我的申请中,订单是这样的:

 0: WebAsyncManagerIntegrationFilter
1: SecurityContextPersistenceFilter
2: HeaderWriterFilter
...

第 2 步:使用 Spring 的 WebSecurityConfigurerAdapter 和 HttpSecurity 将过滤器插入所需位置

您可能已经有了 WebSecurityConfigurerAdapter@Override configure(HttpSecurity http) 方法。 HttpSecurity 公开 addFilterBeforeaddFilterAfter 方法,允许您将过滤器相对于链中的现有类放置。您的过滤器(实例)是这些方法的第一个参数,您要在之前或之后插入的过滤器的类是第二个参数。

就我而言,我希望我的自定义日志记录过滤器成为链中的第一个(我的代码片段是 Kotlin,我将把 Java 实现留给你):

 override fun configure(http: HttpSecurity) {
    http
        .addFilterBefore(MyCustomLoggingFilter(), WebAsyncManagerIntegrationFilter::class.java)
        .authorizeRequests()
        .antMatchers(
        ...
        )
}

第 3 步:获利!

使用上面第 1 步中描述的调试方法来验证您的过滤器是否在过滤器链中您想要的位置。

希望这可以帮助其他人。

原文由 Nate Vaughan 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题