I'm building a Spring Boot v3.1.1
application using Spring Security as a dependency.
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
}
I have created two custom filters expecting that they run after (last in the chain) Spring Security filters:
@Order(1)
@Component
public class DeviceFilter extends OncePerRequestFilter {}
@Order(2)
@Component
public class MdcFilter extends OncePerRequestFilter {}
They are working, but I cannot confirm that the order is correct.
I have tried this:
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable) // Removes CsrfFilter
.logout(AbstractHttpConfigurer::disable) // Removes LogoutFilter
.rememberMe(AbstractHttpConfigurer::disable) // Removes RememberMeAuthenticationFilter
.requestCache(RequestCacheConfigurer::disable) // Removes RequestCacheAwareFilter
.cors(withDefaults()) // Adds CorsFilter
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth2 -> oauth2.jwt(withDefaults()));
return http.build();
}
}
Result in the console:
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CorsFilter
BearerTokenAuthenticationFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
AuthorizationFilter
]
If you can notice, my two custom filters are not there, but they are working somehow.
I think that Spring Security filters are independent of custom filters, and these are not added to the array of filters that they manage. I'm not sure, I'm not an expert on the subject.
Also, I have tried to put logs inside of my two custom filters to check the order. They are good.
09:05AM INFO DeviceFilter : {} DeviceFilter!!!!!!!
09:05AM INFO MdcFilter : {} MdcFilter!!!!!!!
But so far, I cannot guarantee that they are running after Spring Security filters. The reason is that I only want them to run if the user is successfully authenticated and has passed all the Spring Security checks.
Another thing that I have tried is to add my filters inside the securityFilterChain()
method, this implies that my filters no longer implement @Order
neither @Component
:
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// .......
// ......
.addFilterAfter(new DeviceFilter(), AuthorizationFilter.class);
.addFilterAfter(new MdcFilter(), DeviceFilter.class);
return http.build();
}
}
Result in the console:
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CorsFilter
BearerTokenAuthenticationFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
AuthorizationFilter
DeviceFilter // <=================
MdcFilter // <=================
]
I would prefer to stick with the @Order and @Component approach because it's easier for me.
In other threads, they talk about how to set the order.
- Controlling the order of non-security Filters in a Spring Boot app using Spring Security
- Filter order in spring-boot
My question is how to confirm that the order I have (using @Order and @Component) is correct and they are running after Spring Security filters?
Thanks in advance and any push on this is appreciated.