Java spring-boot中的过滤顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25957879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 01:35:32  来源:igfitidea点击:

Filter order in spring-boot

javaspringspring-mvcspring-boot

提问by igo

How can I specify order of my Filter in spring-boot? I need to insert my MDC filter after Spring Security filter. I tried almost everything but my filter was always first. This didn't work:

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

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

This didn't work too:

这也不起作用:

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

采纳答案by igo

Guys from Spring helped again. See https://github.com/spring-projects/spring-boot/issues/1640and https://jira.spring.io/browse/SEC-2730

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

Spring Security doesn't set an order on the Filter bean that it creates. This means that, when Boot is creating a FilterRegistrationBean for it, it gets the default order which is LOWEST_PRECEDENCE.

If you want your own Filter to go after Spring Security's you can create your own registration for Spring Security's filter and specify the order.

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

如果您希望自己的过滤器遵循 Spring Security 的过滤器,您可以为 Spring Security 的过滤器创建自己的注册并指定顺序。

So the answer to my question is:

所以我的问题的答案是:

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

回答by Mikhail

This was fixed in Spring Boot 1.2. The security chain now defaults to order 0.

这在 Spring Boot 1.2 中得到了修复。安全链现在默认为 order 0

It can also be set via properties:

也可以通过属性设置:

security.filter-order=0 # Security filter chain order.

https://github.com/spring-projects/spring-boot/issues/1640

https://github.com/spring-projects/spring-boot/issues/1640

回答by Nate Vaughan

Here's an answer compatible with Spring Boot 2 / Spring Security 5 that will allow you to insert your filter in an arbitrary place in the filter chain.

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

My use case was a custom logging javax.servlet.Filterthat I wanted to execute before any Spring Security filters; however the below steps should allow you to put a filter anywhere in your existing Spring filter chain:

我的用例是javax.servlet.Filter我想在任何 Spring Security 过滤器之前执行的自定义日志记录;但是,以下步骤应该允许您在现有 Spring 过滤器链中的任何位置放置过滤器:

Step 1: Find out the order of Spring filters in your existing setup.

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

Connect your favorite remote debugger to your application, and set a breakpoint in the doFilter(ServletRequest request, ServletResponse response)method of org.springframework.security.web.FilterChainProxy. As of Spring Security 5.1.6, that is line 311. In your debugger, find out the existing filters by inspecting this.additionalFilters. In my application, the order was something like:

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

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

Step 2: Insert your filter in the desired place using Spring's WebSecurityConfigurerAdapter and HttpSecurity

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

You likely already have a WebSecurityConfigurerAdapterwith a @Override configure(HttpSecurity http)method. HttpSecurityexposes addFilterBeforeand addFilterAftermethods to allow you to place your filter relative to an existing class in the chain. Your filter (instance) is the first argument of these methods, and the class of the filter you'd like to insert before or after is the second argument.

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

In my case, I wanted my custom logging filter to be first in the chain (my code snippet is Kotlin, I'll leave the Java implementation to you):

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

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

Step 3: Profit!

第 3 步:获利!

Use the debugging method described in Step 1 above to verify that your filter is where you intended in the filter chain.

使用上面步骤 1 中描述的调试方法来验证您的过滤器是否位于过滤器链中的预期位置。

Hope this helps someone else out there.

希望这可以帮助其他人。