Skip to content

Commit 45bbd86

Browse files
hanrwSteve Riesenberg
authored andcommitted
HttpSecurityDsl should support apply method
Closes gh-11754
1 parent 355ef21 commit 45bbd86

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

config/src/main/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDsl.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ package org.springframework.security.config.web.servlet
1818

1919
import org.springframework.context.ApplicationContext
2020
import org.springframework.security.authentication.AuthenticationManager
21+
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
2122
import org.springframework.security.config.annotation.web.builders.HttpSecurity
2223
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
2324
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
25+
import org.springframework.security.web.DefaultSecurityFilterChain
2426
import org.springframework.security.web.util.matcher.RequestMatcher
2527
import org.springframework.util.ClassUtils
2628
import javax.servlet.Filter
@@ -75,6 +77,35 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
7577

7678
var authenticationManager: AuthenticationManager? = null
7779

80+
/**
81+
* Applies a [SecurityConfigurerAdapter] to this [HttpSecurity]
82+
*
83+
* Example:
84+
*
85+
* ```
86+
* @Configuration
87+
* @EnableWebSecurity
88+
* class SecurityConfig {
89+
*
90+
* @Bean
91+
* fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
92+
* http {
93+
* apply(CustomSecurityConfigurer<HttpSecurity>()) {
94+
* customProperty = "..."
95+
* }
96+
* }
97+
* return http.build()
98+
* }
99+
* }
100+
* ```
101+
*
102+
* @param configurer
103+
* the [SecurityConfigurerAdapter] for further customizations
104+
*/
105+
fun <C : SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> apply(configurer: C, configuration: C.() -> Unit = { }): C {
106+
return this.http.apply(configurer).apply(configuration)
107+
}
108+
78109
/**
79110
* Allows configuring the [HttpSecurity] to only be invoked when matching the
80111
* provided pattern.

config/src/test/kotlin/org/springframework/security/config/web/servlet/HttpSecurityDslTests.kt

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import io.mockk.verify
2222
import org.assertj.core.api.Assertions.assertThat
2323
import org.junit.jupiter.api.Test
2424
import org.junit.jupiter.api.extension.ExtendWith
25+
import org.junit.jupiter.params.ParameterizedTest
26+
import org.junit.jupiter.params.provider.ValueSource
2527
import org.springframework.beans.factory.annotation.Autowired
2628
import org.springframework.context.annotation.Bean
2729
import org.springframework.context.annotation.Configuration
@@ -30,16 +32,19 @@ import org.springframework.security.authentication.AuthenticationManager
3032
import org.springframework.security.authentication.ProviderManager
3133
import org.springframework.security.authentication.TestingAuthenticationProvider
3234
import org.springframework.security.authentication.TestingAuthenticationToken
35+
import org.springframework.security.config.annotation.web.HttpSecurityBuilder
3336
import org.springframework.security.config.annotation.web.builders.HttpSecurity
3437
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
3538
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
39+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer
3640
import org.springframework.security.config.test.SpringTestContext
3741
import org.springframework.security.config.test.SpringTestContextExtension
3842
import org.springframework.security.core.userdetails.User
3943
import org.springframework.security.core.userdetails.UserDetailsService
4044
import org.springframework.security.provisioning.InMemoryUserDetailsManager
4145
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
4246
import org.springframework.security.web.FilterChainProxy
47+
import org.springframework.security.web.SecurityFilterChain
4348
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
4449
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
4550
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
@@ -53,9 +58,6 @@ import org.springframework.test.web.servlet.post
5358
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
5459
import org.springframework.web.servlet.config.annotation.EnableWebMvc
5560
import javax.servlet.Filter
56-
import org.junit.jupiter.params.ParameterizedTest
57-
import org.junit.jupiter.params.provider.ValueSource
58-
import org.springframework.security.web.SecurityFilterChain
5961

6062
/**
6163
* Tests for [HttpSecurityDsl]
@@ -483,4 +485,42 @@ class HttpSecurityDslTests {
483485
}
484486

485487
class CustomFilter : UsernamePasswordAuthenticationFilter()
488+
489+
@Test
490+
fun `HTTP security when apply custom security configurer then custom filter added to filter chain`() {
491+
this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire()
492+
493+
val filterChain = spring.context.getBean(FilterChainProxy::class.java)
494+
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass }
495+
496+
assertThat(filterClasses).contains(
497+
CustomFilter::class.java
498+
)
499+
}
500+
501+
@Configuration
502+
@EnableWebSecurity
503+
@EnableWebMvc
504+
open class CustomSecurityConfigurerConfig {
505+
@Bean
506+
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
507+
http {
508+
apply(CustomSecurityConfigurer<HttpSecurity>()) {
509+
filter = CustomFilter()
510+
}
511+
}
512+
return http.build()
513+
}
514+
}
515+
516+
class CustomSecurityConfigurer<H : HttpSecurityBuilder<H>> : AbstractHttpConfigurer<CustomSecurityConfigurer<H>, H>() {
517+
var filter: Filter? = null
518+
override fun init(builder: H) {
519+
filter = filter ?: UsernamePasswordAuthenticationFilter()
520+
}
521+
522+
override fun configure(builder: H) {
523+
builder.addFilterBefore(CustomFilter(), UsernamePasswordAuthenticationFilter::class.java)
524+
}
525+
}
486526
}

0 commit comments

Comments
 (0)