I am trying to add my custom filter after Spring Security but I am unable to set order of filters. None of examples below work. My filter is alway added to the beginning of the chain.
@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;
}
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. For example:
@Bean
public FilterRegistrationBean securityFilterChain(
@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) {
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
registration.setOrder(0);
registration
.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
return registration;
}
@rwinch Does it make sense to change Spring Security to set an order on the springSecurityFilterChain
bean created in WebSecurityConfiguration
so that it's something higher than LOWEST_PRECEDENCE
by default?
Since ordering is so important, I'm a little hesitant to do this as it can impact the security of an application. Please feel free to create a JIRA for consideration.
Thanks, Rob. I've opened SEC-2730.
Hmm, I'm now bouncing against this issue as well.
Isn't it strange that the Spring Security filter is registered with LOWEST_PRECEDENCE
by default?
I would have expected highest precedence to be honest..
Can we at least make is easier to change the order in Boot? Maybe a application property?
Most people want to avoid the coding the FilterRegistrationBean for the securityFilterChain(..).
I too was surprised that it was LOWEST_PRECEDENCE
as I'd expected that you'd want the security filter to run as early as possible. I'll defer to @rwinch on that though.
If changing the precedence is that right thing to do, then I'd rather the change was made in Spring Security. If Rob tells us it's not the right thing to do then I'm not sure that we want to make it easy for people to do it. In short, let's wait and see what @rwinch says.
OK I agree. In all cases I've seen the security filter would always have been the first filter. Before request logging filter, mdc filter etc.
Anyway let's see what @rwinch says.
Spring Security is not always the first Filter. A few examples that come to mind are:
OpenEntityManagerInViewFilter
must be first when using JPA in Spring Security code,CharacterEncodingFilter
should typically be before Spring SecuritySessionRepositoryFilter
must be before Spring Security in order to ensure the HttpSession
is overridden before Spring Security is invokedFilter
s are often best placed before Spring SecurityMultipartFilter
must be first when handling multipart file uploads with CSRF protectionSo a few things we must consider...
What are the order values of these other Filter's? Do we have a "well known" specification for them?
I wonder why setting an order on Filter matters for Spring Security in general. It seems that Order only matters in Boot applications. Can we think of other reasons that Order being specified provides value?
If the only reason is for Boot applications, then it seems we are running into a slippery slope. Why not have Spring's ApplicationInitializer's automatically add the Filter's at that point? Note I don't agree with dong this, but am pointing out that if order only makes sense in the context of boot, then we likely need to figure out a way to keep that logic there.
OK, so I think there should be an easy way to set the security filter somewhere in the middle
.
Above suggestion is to set the order to 0
but now I wonder what the default Order
is for e.g. OpenEntityManagerInViewFilter
, CharacterEncodingFilter
etc.
I think many Boot users won't understand how to set this up correctly.
NOTE: If Spring Security was specifying an order at all, then I would agree that it is something that needs to change in Spring Security. However, Spring Security does not set any Order
on the springSecurityFilterChain (Why would it other than a Boot context?) which semantically is quite a bit different than specifying it as Ordered.LOWEST_PRECEDENCE
. In the Boot context, it sorts the Filters using AnnotationAwareOrderComparator
which treats anything that does not have an @Order
annotation and does not implement Ordered
as Ordered.LOWEST_PRECEDENCE
. So that is why I asked "Can we think of other reasons that Order being specified provides value?" Without an answer to this, I think it may not make sense for Spring Security to do this. In that case, it may make sense to have Boot use OrderSourceProvider
and metadata to determine the sorted order.
Thanks, Rob. It's certainly Boot that's responsible for finding Filter
beans in the application context and auto-registering them with the servlet container. That, plus the points you've made above, goes quite a long way to convincing me that it should be Boot that fixes this. The other filters that you've mentioned aren't, as far as I'm aware, automatically configured so it's up to the user to specify an order when they configure them.
@wilkinsona What do you suggest to do then? Based on feedback from @rwinch there are many filters that should be before the security filter, on the other (as we both expected) there are also many cases where we expect filters after the security filter.
Wouldn't it be better that Boot auto configuration configures it somewhere in the middle
? Like order 0
as in the code you posted. Probably use a constant so we can refer to the value from other registrations. At least this gives a easy solution to configure our own filters before and after the security filter and we don't have to tamper with the order of the security filter in each project. Like I said many won't fully understand how to do this.
@marceloverdijk What you've described is pretty much exactly what I think we should do
Thx!
Most helpful comment
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 isLOWEST_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. For example:
@rwinch Does it make sense to change Spring Security to set an order on the
springSecurityFilterChain
bean created inWebSecurityConfiguration
so that it's something higher thanLOWEST_PRECEDENCE
by default?