From a2413369e83da5ce6f4f0e754b4da76b9d8e4c28 Mon Sep 17 00:00:00 2001 From: Markus Engelbrecht Date: Fri, 3 Apr 2020 05:15:08 +0200 Subject: [PATCH 1/2] Add addFilterAfter and addFilterBefore to Kotlin DSL Fixes gh-8316 --- .../config/web/servlet/HttpSecurityDsl.kt | 50 ++++++++++++++++++ .../web/servlet/HttpSecurityDslTests.kt | 52 +++++++++++++++++++ 2 files changed, 102 insertions(+) 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..709924878d4 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 @@ -239,4 +239,56 @@ class HttpSecurityDslTests { class CustomFilter : UsernamePasswordAuthenticationFilter() } + + @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, + CustomFilterAfterConfig.CustomFilter::class.java + ) + } + + @EnableWebSecurity + @EnableWebMvc + open class CustomFilterAfterConfig : WebSecurityConfigurerAdapter() { + override fun configure(http: HttpSecurity) { + http { + addFilterAfter(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + formLogin {} + } + } + + class CustomFilter : UsernamePasswordAuthenticationFilter() + } + + @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( + CustomFilterBeforeConfig.CustomFilter::class.java, + UsernamePasswordAuthenticationFilter::class.java + ) + } + + @EnableWebSecurity + @EnableWebMvc + open class CustomFilterBeforeConfig : WebSecurityConfigurerAdapter() { + override fun configure(http: HttpSecurity) { + http { + addFilterBefore(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + formLogin {} + } + } + + class CustomFilter : UsernamePasswordAuthenticationFilter() + } } From 95af4d1a12c367fcaa895d83f1a905704d6a26c4 Mon Sep 17 00:00:00 2001 From: Markus Engelbrecht Date: Fri, 3 Apr 2020 17:32:34 +0200 Subject: [PATCH 2/2] Move CustomFilter outside of the configuration classes to enable reuse --- .../config/web/servlet/HttpSecurityDslTests.kt | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) 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 709924878d4..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,8 +236,6 @@ class HttpSecurityDslTests { addFilterAt(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) } } - - class CustomFilter : UsernamePasswordAuthenticationFilter() } @Test @@ -249,7 +247,7 @@ class HttpSecurityDslTests { assertThat(filters).containsSubsequence( UsernamePasswordAuthenticationFilter::class.java, - CustomFilterAfterConfig.CustomFilter::class.java + CustomFilter::class.java ) } @@ -262,8 +260,6 @@ class HttpSecurityDslTests { formLogin {} } } - - class CustomFilter : UsernamePasswordAuthenticationFilter() } @Test @@ -274,7 +270,7 @@ class HttpSecurityDslTests { val filters: List> = filterChain.getFilters("/").map { it.javaClass } assertThat(filters).containsSubsequence( - CustomFilterBeforeConfig.CustomFilter::class.java, + CustomFilter::class.java, UsernamePasswordAuthenticationFilter::class.java ) } @@ -288,7 +284,7 @@ class HttpSecurityDslTests { formLogin {} } } - - class CustomFilter : UsernamePasswordAuthenticationFilter() } + + class CustomFilter : UsernamePasswordAuthenticationFilter() }