diff --git a/config/src/main/kotlin/org/springframework/security/config/web/servlet/HeadersDsl.kt b/config/src/main/kotlin/org/springframework/security/config/web/servlet/HeadersDsl.kt index ae1d9d945e..833f2474b7 100644 --- a/config/src/main/kotlin/org/springframework/security/config/web/servlet/HeadersDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/web/servlet/HeadersDsl.kt @@ -19,6 +19,7 @@ package org.springframework.security.config.web.servlet import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer import org.springframework.security.config.web.servlet.headers.* +import org.springframework.security.web.header.HeaderWriter import org.springframework.security.web.header.writers.* import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter @@ -41,6 +42,7 @@ class HeadersDsl { private var referrerPolicy: ((HeadersConfigurer.ReferrerPolicyConfig) -> Unit)? = null private var featurePolicyDirectives: String? = null private var disabled = false + private var headerWriters = mutableListOf() var defaultsDisabled: Boolean? = null @@ -162,6 +164,16 @@ class HeadersDsl { this.featurePolicyDirectives = policyDirectives } + /** + * Adds a [HeaderWriter] instance. + * + * @param headerWriter the [HeaderWriter] instance to add + * @since 5.4 + */ + fun addHeaderWriter(headerWriter: HeaderWriter) { + this.headerWriters.add(headerWriter) + } + /** * Disable all HTTP security headers. * @@ -205,6 +217,9 @@ class HeadersDsl { featurePolicyDirectives?.also { headers.featurePolicy(featurePolicyDirectives) } + headerWriters.forEach { headerWriter -> + headers.addHeaderWriter(headerWriter) + } if (disabled) { headers.disable() } diff --git a/config/src/test/kotlin/org/springframework/security/config/web/servlet/HeadersDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/web/servlet/HeadersDslTests.kt index b535e36b35..c16c504710 100644 --- a/config/src/test/kotlin/org/springframework/security/config/web/servlet/HeadersDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/web/servlet/HeadersDslTests.kt @@ -24,6 +24,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.config.test.SpringTestRule +import org.springframework.security.web.header.writers.StaticHeadersWriter 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 @@ -118,4 +119,25 @@ class HeadersDslTests { } } } + + @Test + fun `request when custom header writer then custom header in response`() { + this.spring.register(HeaderWriterConfig::class.java).autowire() + + this.mockMvc.get("/") + .andExpect { + header { string("custom-header", "custom-value") } + } + } + + @EnableWebSecurity + open class HeaderWriterConfig : WebSecurityConfigurerAdapter() { + override fun configure(http: HttpSecurity) { + http { + headers { + addHeaderWriter(StaticHeadersWriter("custom-header", "custom-value")) + } + } + } + } }