diff --git a/config/src/main/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDsl.kt b/config/src/main/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDsl.kt index 6c672a8d1f2..492d5e1c5c6 100644 --- a/config/src/main/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDsl.kt @@ -669,6 +669,56 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu this.http.addFilterAt(filter, atFilter) } + /** + * Adds the [Filter] after the location of the specified [Filter] class. + * + * Example: + * + * ``` + * @EnableWebSecurity + * class SecurityConfig : WebSecurityConfigurerAdapter() { + * + * override fun configure(http: HttpSecurity) { + * http { + * addFilterAfter(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + * } + * } + * } + * ``` + * + * @param filter the [Filter] to register + * @param afterFilter the location of another [Filter] that is already registered + * (i.e. known) with Spring Security. + */ + fun addFilterAfter(filter: Filter, afterFilter: Class) { + this.http.addFilterAfter(filter, afterFilter) + } + + /** + * Adds the [Filter] before the location of the specified [Filter] class. + * + * Example: + * + * ``` + * @EnableWebSecurity + * class SecurityConfig : WebSecurityConfigurerAdapter() { + * + * override fun configure(http: HttpSecurity) { + * http { + * addFilterBefore(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + * } + * } + * } + * ``` + * + * @param filter the [Filter] to register + * @param beforeFilter the location of another [Filter] that is already registered + * (i.e. known) with Spring Security. + */ + fun addFilterBefore(filter: Filter, beforeFilter: Class) { + this.http.addFilterBefore(filter, beforeFilter) + } + /** * Apply all configurations to the provided [HttpSecurity] */ diff --git a/config/src/test/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDslTests.kt index 7dd3de75212..83b1234f9d1 100644 --- a/config/src/test/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDslTests.kt @@ -225,7 +225,7 @@ class HttpSecurityDslTests { val filters: List = filterChain.getFilters("/") assertThat(filters).hasSize(1) - assertThat(filters[0]).isExactlyInstanceOf(CustomFilterConfig.CustomFilter::class.java) + assertThat(filters[0]).isExactlyInstanceOf(CustomFilter::class.java) } @EnableWebSecurity @@ -236,7 +236,55 @@ class HttpSecurityDslTests { addFilterAt(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) } } + } + + @Test + fun `HTTP security when custom filter configured then custom filter added after specific filter to filter chain`() { + this.spring.register(CustomFilterAfterConfig::class.java).autowire() + + val filterChain = spring.context.getBean(FilterChainProxy::class.java) + val filters: List> = filterChain.getFilters("/").map { it.javaClass } + + assertThat(filters).containsSubsequence( + UsernamePasswordAuthenticationFilter::class.java, + CustomFilter::class.java + ) + } + + @EnableWebSecurity + @EnableWebMvc + open class CustomFilterAfterConfig : WebSecurityConfigurerAdapter() { + override fun configure(http: HttpSecurity) { + http { + addFilterAfter(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + formLogin {} + } + } + } + + @Test + fun `HTTP security when custom filter configured then custom filter added before specific filter to filter chain`() { + this.spring.register(CustomFilterBeforeConfig::class.java).autowire() + + val filterChain = spring.context.getBean(FilterChainProxy::class.java) + val filters: List> = filterChain.getFilters("/").map { it.javaClass } + + assertThat(filters).containsSubsequence( + CustomFilter::class.java, + UsernamePasswordAuthenticationFilter::class.java + ) + } - class CustomFilter : UsernamePasswordAuthenticationFilter() + @EnableWebSecurity + @EnableWebMvc + open class CustomFilterBeforeConfig : WebSecurityConfigurerAdapter() { + override fun configure(http: HttpSecurity) { + http { + addFilterBefore(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + formLogin {} + } + } } + + class CustomFilter : UsernamePasswordAuthenticationFilter() }