Whilst looking at https://github.com/spring-projects/spring-boot/issues/23421 I noticed a few of our migrations use the @Order annotation on beans.
A common pattern would be:
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcher(this.url)).authorizeRequests().anyRequest().anonymous().and()
.csrf().disable();
return http.build();
}
and
@Bean
@Order(SecurityProperties.IGNORED_ORDER)
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**"));
}
I'm not convinced that these @Order annotations are working in these locations (or perhaps they're not supposed to be used that way).
Looking at the code, I think WebSecurityConfiguration.setWebSecurityCustomizers and WebSecurityConfiguration.setFilterChains are responsible for managing the beans and they sort items directly. I'm pretty sure that this doesn't consider any annotations on the @Bean method.
I think that using ObjectProvider.orderedStream() might be a better choice since it will wire up a FactoryAwareOrderSourceProvider OrderComparator.OrderSourceProvider
Comment From: eleftherias
@philwebb We had an existing test checking the order on SecurityFilterChain and I just added an additional one for WebSecurityCustomizer.
As far as I can tell, the @Order annotation is working.
Do you have an example configuration where they aren't being ordered correctly?
Comment From: philwebb
@eleftherias I'm afraid not, it was just an observation from looking at the code. I may well have got it wrong. Perhaps Spring is injecting the list already sorted and re-sorting it doesn't cause a side-effect. I'll close this one since the tests seem to prove it's working.
Comment From: mbhave
@eleftherias Here is an example where Spring Security's sort will flip the order that Spring Framework injected them in:
@Bean
@Order(1)
SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
//something
return http.build();
}
@Bean
TestSecurityFilterChain securityFilterChain2(HttpSecurity http) throws Exception {
return new TestSecurityFilterChain();
}
@Order(2)
static class TestSecurityFilterChain implements SecurityFilterChain {
//implement methods
}
Spring Framework will inject securityFilterChain1, securityFilterChain2. Then Spring Security will sort them again using securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE);. It sees @Order on TestSecurityFilterChain but nothing on securityFilterChain1 because it does not look at bean definitions. securityFilterChain2 will then end up before securityFilterChain1. I don't see a need for Spring Security to call securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE); and it seems like it could be dropped.
Comment From: eleftherias
Thanks for the sample @mbhave. I'm reopening the issue.