From a5210aaf9b4703524f3d4a5dddaf60654680aa4a Mon Sep 17 00:00:00 2001 From: Eleftheria Stein Date: Mon, 10 Feb 2020 11:45:09 +0100 Subject: [PATCH] Support custom filter in Kotlin DSL Fixes: gh-7951 --- .../config/web/servlet/HttpSecurityDsl.kt | 26 ++++++++++++++++++ .../web/servlet/HttpSecurityDslTests.kt | 27 +++++++++++++++++++ 2 files changed, 53 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 909ffb7fa6..8447c7b6bf 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 @@ -22,6 +22,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository import org.springframework.security.web.util.matcher.RequestMatcher import org.springframework.util.ClassUtils +import javax.servlet.Filter import javax.servlet.http.HttpServletRequest /** @@ -642,6 +643,31 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu this.http.oauth2ResourceServer(oauth2ResourceServerCustomizer) } + /** + * Adds the [Filter] at the location of the specified [Filter] class. + * + * Example: + * + * ``` + * @EnableWebSecurity + * class SecurityConfig : WebSecurityConfigurerAdapter() { + * + * override fun configure(http: HttpSecurity) { + * http { + * addFilterAt(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + * } + * } + * } + * ``` + * + * @param filter the [Filter] to register + * @param atFilter the location of another [Filter] that is already registered + * (i.e. known) with Spring Security. + */ + fun addFilterAt(filter: Filter, atFilter: Class) { + this.http.addFilterAt(filter, atFilter) + } + /** * 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 4c8fc8d12c..7dd3de7521 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 @@ -16,6 +16,7 @@ package org.springframework.security.config.web.servlet +import org.assertj.core.api.Assertions.assertThat import org.junit.Rule import org.junit.Test import org.springframework.beans.factory.annotation.Autowired @@ -29,6 +30,8 @@ import org.springframework.security.config.test.SpringTestRule import org.springframework.security.core.userdetails.User import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.provisioning.InMemoryUserDetailsManager +import org.springframework.security.web.FilterChainProxy +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter @@ -39,6 +42,7 @@ import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get import org.springframework.test.web.servlet.post import org.springframework.web.servlet.config.annotation.EnableWebMvc +import javax.servlet.Filter /** * Tests for [HttpSecurityDsl] @@ -212,4 +216,27 @@ class HttpSecurityDslTests { } } } + + @Test + fun `HTTP security when custom filter configured then custom filter added to filter chain`() { + this.spring.register(CustomFilterConfig::class.java).autowire() + + val filterChain = spring.context.getBean(FilterChainProxy::class.java) + val filters: List = filterChain.getFilters("/") + + assertThat(filters).hasSize(1) + assertThat(filters[0]).isExactlyInstanceOf(CustomFilterConfig.CustomFilter::class.java) + } + + @EnableWebSecurity + @EnableWebMvc + open class CustomFilterConfig : WebSecurityConfigurerAdapter(true) { + override fun configure(http: HttpSecurity) { + http { + addFilterAt(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java) + } + } + + class CustomFilter : UsernamePasswordAuthenticationFilter() + } }