Merge branch '5.8.x'
This commit is contained in:
commit
76fbca9f46
|
@ -729,7 +729,10 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
* If false, will not specify the mode as blocked. In this instance, any content
|
* If false, will not specify the mode as blocked. In this instance, any content
|
||||||
* will be attempted to be fixed. If true, the content will be replaced with "#".
|
* will be attempted to be fixed. If true, the content will be replaced with "#".
|
||||||
* @param enabled the new value
|
* @param enabled the new value
|
||||||
|
* @deprecated use
|
||||||
|
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public XXssConfig block(boolean enabled) {
|
public XXssConfig block(boolean enabled) {
|
||||||
this.writer.setBlock(enabled);
|
this.writer.setBlock(enabled);
|
||||||
return this;
|
return this;
|
||||||
|
@ -757,12 +760,49 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
* X-XSS-Protection: 0
|
* X-XSS-Protection: 0
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param enabled the new value
|
* @param enabled the new value
|
||||||
|
* @deprecated use
|
||||||
|
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public XXssConfig xssProtectionEnabled(boolean enabled) {
|
public XXssConfig xssProtectionEnabled(boolean enabled) {
|
||||||
this.writer.setEnabled(enabled);
|
this.writer.setEnabled(enabled);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the X-XSS-PROTECTION header. OWASP recommends using
|
||||||
|
* {@link XXssProtectionHeaderWriter.HeaderValue#DISABLED}.
|
||||||
|
*
|
||||||
|
* If {@link XXssProtectionHeaderWriter.HeaderValue#DISABLED}, will specify that
|
||||||
|
* X-XSS-Protection is disabled. For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 0
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* If {@link XXssProtectionHeaderWriter.HeaderValue#ENABLED}, will contain a value
|
||||||
|
* of 1, but will not specify the mode as blocked. In this instance, any content
|
||||||
|
* will be attempted to be fixed. For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* If {@link XXssProtectionHeaderWriter.HeaderValue#ENABLED_MODE_BLOCK}, will
|
||||||
|
* contain a value of 1 and will specify mode as blocked. The content will be
|
||||||
|
* replaced with "#". For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1 ; mode=block
|
||||||
|
* </pre>
|
||||||
|
* @param headerValue the new header value
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public XXssConfig headerValue(XXssProtectionHeaderWriter.HeaderValue headerValue) {
|
||||||
|
this.writer.setHeaderValue(headerValue);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables X-XSS-Protection header (does not include it)
|
* Disables X-XSS-Protection header (does not include it)
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
* @return the {@link HeadersConfigurer} for additional configuration
|
||||||
|
|
|
@ -2861,6 +2861,18 @@ public class ServerHttpSecurity {
|
||||||
return HeaderSpec.this;
|
return HeaderSpec.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of x-xss-protection header. OWASP recommends using
|
||||||
|
* {@link XXssProtectionServerHttpHeadersWriter.HeaderValue#DISABLED}.
|
||||||
|
* @param headerValue the headerValue
|
||||||
|
* @return the {@link HeaderSpec} to continue configuring
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public HeaderSpec headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue headerValue) {
|
||||||
|
HeaderSpec.this.xss.setHeaderValue(headerValue);
|
||||||
|
return HeaderSpec.this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web.headers
|
||||||
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||||
|
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin DSL to configure the [HttpSecurity] XSS protection header using
|
* A Kotlin DSL to configure the [HttpSecurity] XSS protection header using
|
||||||
|
@ -28,11 +29,15 @@ import org.springframework.security.config.annotation.web.configurers.HeadersCon
|
||||||
* @property block whether to specify the mode as blocked
|
* @property block whether to specify the mode as blocked
|
||||||
* @property xssProtectionEnabled if true, the header value will contain a value of 1.
|
* @property xssProtectionEnabled if true, the header value will contain a value of 1.
|
||||||
* If false, will explicitly disable specify that X-XSS-Protection is disabled.
|
* If false, will explicitly disable specify that X-XSS-Protection is disabled.
|
||||||
|
* @property headerValue the value of the X-XSS-Protection header. OWASP recommends [HeaderValue.DISABLED].
|
||||||
*/
|
*/
|
||||||
@HeadersSecurityMarker
|
@HeadersSecurityMarker
|
||||||
class XssProtectionConfigDsl {
|
class XssProtectionConfigDsl {
|
||||||
|
@Deprecated("use headerValue instead")
|
||||||
var block: Boolean? = null
|
var block: Boolean? = null
|
||||||
|
@Deprecated("use headerValue instead")
|
||||||
var xssProtectionEnabled: Boolean? = null
|
var xssProtectionEnabled: Boolean? = null
|
||||||
|
var headerValue: HeaderValue? = null
|
||||||
|
|
||||||
private var disabled = false
|
private var disabled = false
|
||||||
|
|
||||||
|
@ -47,6 +52,7 @@ class XssProtectionConfigDsl {
|
||||||
return { xssProtection ->
|
return { xssProtection ->
|
||||||
block?.also { xssProtection.block(block!!) }
|
block?.also { xssProtection.block(block!!) }
|
||||||
xssProtectionEnabled?.also { xssProtection.xssProtectionEnabled(xssProtectionEnabled!!) }
|
xssProtectionEnabled?.also { xssProtection.xssProtectionEnabled(xssProtectionEnabled!!) }
|
||||||
|
headerValue?.also { xssProtection.headerValue(headerValue) }
|
||||||
|
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
xssProtection.disable()
|
xssProtection.disable()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,16 +16,21 @@
|
||||||
|
|
||||||
package org.springframework.security.config.web.server
|
package org.springframework.security.config.web.server
|
||||||
|
|
||||||
|
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter.HeaderValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin DSL to configure the [ServerHttpSecurity] XSS protection header using
|
* A Kotlin DSL to configure the [ServerHttpSecurity] XSS protection header using
|
||||||
* idiomatic Kotlin code.
|
* idiomatic Kotlin code.
|
||||||
*
|
*
|
||||||
|
* @property headerValue the value of the X-XSS-Protection header. OWASP recommends [HeaderValue.DISABLED].
|
||||||
|
*
|
||||||
* @author Eleftheria Stein
|
* @author Eleftheria Stein
|
||||||
* @since 5.4
|
* @since 5.4
|
||||||
*/
|
*/
|
||||||
@ServerSecurityMarker
|
@ServerSecurityMarker
|
||||||
class ServerXssProtectionDsl {
|
class ServerXssProtectionDsl {
|
||||||
private var disabled = false
|
private var disabled = false
|
||||||
|
var headerValue: HeaderValue? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables cache control response headers
|
* Disables cache control response headers
|
||||||
|
@ -36,6 +41,7 @@ class ServerXssProtectionDsl {
|
||||||
|
|
||||||
internal fun get(): (ServerHttpSecurity.HeaderSpec.XssProtectionSpec) -> Unit {
|
internal fun get(): (ServerHttpSecurity.HeaderSpec.XssProtectionSpec) -> Unit {
|
||||||
return { xss ->
|
return { xss ->
|
||||||
|
headerValue?.also { xss.headerValue(headerValue) }
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
xss.disable()
|
xss.disable()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2021 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -38,6 +38,7 @@ import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicy
|
||||||
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
||||||
|
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
@ -59,6 +60,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||||
* @author Vedran Pavic
|
* @author Vedran Pavic
|
||||||
* @author Eleftheria Stein
|
* @author Eleftheria Stein
|
||||||
* @author Marcus Da Coregio
|
* @author Marcus Da Coregio
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringTestContextExtension.class)
|
@ExtendWith(SpringTestContextExtension.class)
|
||||||
public class HeadersConfigurerTests {
|
public class HeadersConfigurerTests {
|
||||||
|
@ -172,6 +174,15 @@ public class HeadersConfigurerTests {
|
||||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredValueDisabledThenOnlyXssProtectionHeaderInResponse()
|
||||||
|
throws Exception {
|
||||||
|
this.spring.register(XssProtectionValueDisabledConfig.class).autowire();
|
||||||
|
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||||
|
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
|
||||||
|
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
|
public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
|
||||||
this.spring.register(XssProtectionInLambdaConfig.class).autowire();
|
this.spring.register(XssProtectionInLambdaConfig.class).autowire();
|
||||||
|
@ -180,6 +191,15 @@ public class HeadersConfigurerTests {
|
||||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredValueDisabledInLambdaThenOnlyXssProtectionHeaderInResponse()
|
||||||
|
throws Exception {
|
||||||
|
this.spring.register(XssProtectionValueDisabledInLambdaConfig.class).autowire();
|
||||||
|
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||||
|
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
|
||||||
|
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWhenFrameOptionsSameOriginConfiguredThenFrameOptionsHeaderHasValueSameOrigin() throws Exception {
|
public void getWhenFrameOptionsSameOriginConfiguredThenFrameOptionsHeaderHasValueSameOrigin() throws Exception {
|
||||||
this.spring.register(HeadersCustomSameOriginConfig.class).autowire();
|
this.spring.register(HeadersCustomSameOriginConfig.class).autowire();
|
||||||
|
@ -690,6 +710,22 @@ public class HeadersConfigurerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
static class XssProtectionValueDisabledConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.headers()
|
||||||
|
.defaultsDisabled()
|
||||||
|
.xssProtection()
|
||||||
|
.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED);
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class XssProtectionInLambdaConfig extends WebSecurityConfigurerAdapter {
|
static class XssProtectionInLambdaConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@ -708,6 +744,25 @@ public class HeadersConfigurerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
static class XssProtectionValueDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.headers((headers) ->
|
||||||
|
headers
|
||||||
|
.defaultsDisabled()
|
||||||
|
.xssProtection((xXssConfig) ->
|
||||||
|
xXssConfig.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
|
static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -32,6 +32,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.web.header.writers.StaticHeadersWriter;
|
import org.springframework.security.web.header.writers.StaticHeadersWriter;
|
||||||
|
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
|
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
|
||||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
|
@ -282,8 +283,7 @@ public class NamespaceHttpHeadersTests {
|
||||||
// xss-protection@enabled and xss-protection@block
|
// xss-protection@enabled and xss-protection@block
|
||||||
.defaultsDisabled()
|
.defaultsDisabled()
|
||||||
.xssProtection()
|
.xssProtection()
|
||||||
.xssProtectionEnabled(true)
|
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED);
|
||||||
.block(false);
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2021 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -296,6 +296,51 @@ public class HeaderSpecTests {
|
||||||
assertHeaders();
|
assertHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headersWhenXssProtectionValueDisabledThenXssProtectionWritten() {
|
||||||
|
this.expectedHeaders.set(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0");
|
||||||
|
// @formatter:off
|
||||||
|
this.http.headers()
|
||||||
|
.xssProtection()
|
||||||
|
.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.DISABLED);
|
||||||
|
// @formatter:on
|
||||||
|
assertHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headersWhenXssProtectionValueEnabledThenXssProtectionWritten() {
|
||||||
|
this.expectedHeaders.set(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1");
|
||||||
|
// @formatter:off
|
||||||
|
this.http.headers()
|
||||||
|
.xssProtection()
|
||||||
|
.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED);
|
||||||
|
// @formatter:on
|
||||||
|
assertHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headersWhenXssProtectionValueEnabledModeBlockThenXssProtectionWritten() {
|
||||||
|
this.expectedHeaders.set(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block");
|
||||||
|
// @formatter:off
|
||||||
|
this.http.headers()
|
||||||
|
.xssProtection()
|
||||||
|
.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK);
|
||||||
|
// @formatter:on
|
||||||
|
assertHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headersWhenXssProtectionValueDisabledInLambdaThenXssProtectionWritten() {
|
||||||
|
this.expectedHeaders.set(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0");
|
||||||
|
// @formatter:off
|
||||||
|
this.http.headers()
|
||||||
|
.xssProtection((xssProtection) ->
|
||||||
|
xssProtection.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.DISABLED)
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
assertHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void headersWhenFeaturePolicyEnabledThenFeaturePolicyWritten() {
|
public void headersWhenFeaturePolicyEnabledThenFeaturePolicyWritten() {
|
||||||
String policyDirectives = "Feature-Policy";
|
String policyDirectives = "Feature-Policy";
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.security.config.annotation.web.invoke
|
||||||
import org.springframework.security.config.test.SpringTestContext
|
import org.springframework.security.config.test.SpringTestContext
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension
|
import org.springframework.security.config.test.SpringTestContextExtension
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
|
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter
|
||||||
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.get
|
import org.springframework.test.web.servlet.get
|
||||||
|
@ -152,4 +153,32 @@ class XssProtectionConfigDslTests {
|
||||||
return http.build()
|
return http.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `headers when XSS protection header value disabled then X-XSS-Protection header is 0`() {
|
||||||
|
this.spring.register(XssProtectionHeaderValueDisabledFunctionConfig::class.java).autowire()
|
||||||
|
|
||||||
|
this.mockMvc.get("/") {
|
||||||
|
secure = true
|
||||||
|
}.andExpect {
|
||||||
|
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
open class XssProtectionHeaderValueDisabledFunctionConfig () {
|
||||||
|
@Bean
|
||||||
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
|
http {
|
||||||
|
headers {
|
||||||
|
defaultsDisabled = true
|
||||||
|
xssProtection {
|
||||||
|
headerValue = XXssProtectionHeaderWriter.HeaderValue.DISABLED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return http.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -99,4 +99,29 @@ class ServerXssProtectionDslTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `request when xss protection value disabled then xss header in response`() {
|
||||||
|
this.spring.register(XssValueDisabledConfig::class.java).autowire()
|
||||||
|
|
||||||
|
this.client.get()
|
||||||
|
.uri("/")
|
||||||
|
.exchange()
|
||||||
|
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@EnableWebFlux
|
||||||
|
open class XssValueDisabledConfig {
|
||||||
|
@Bean
|
||||||
|
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
||||||
|
return http {
|
||||||
|
headers {
|
||||||
|
xssProtection {
|
||||||
|
headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.DISABLED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,6 +20,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.security.web.header.HeaderWriter;
|
import org.springframework.security.web.header.HeaderWriter;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the <a href=
|
* Renders the <a href=
|
||||||
|
@ -34,25 +35,19 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
|
||||||
|
|
||||||
private static final String XSS_PROTECTION_HEADER = "X-XSS-Protection";
|
private static final String XSS_PROTECTION_HEADER = "X-XSS-Protection";
|
||||||
|
|
||||||
private boolean enabled;
|
private HeaderValue headerValue;
|
||||||
|
|
||||||
private boolean block;
|
|
||||||
|
|
||||||
private String headerValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance
|
* Create a new instance
|
||||||
*/
|
*/
|
||||||
public XXssProtectionHeaderWriter() {
|
public XXssProtectionHeaderWriter() {
|
||||||
this.enabled = true;
|
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
|
||||||
this.block = true;
|
|
||||||
updateHeaderValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||||
if (!response.containsHeader(XSS_PROTECTION_HEADER)) {
|
if (!response.containsHeader(XSS_PROTECTION_HEADER)) {
|
||||||
response.setHeader(XSS_PROTECTION_HEADER, this.headerValue);
|
response.setHeader(XSS_PROTECTION_HEADER, this.headerValue.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,37 +72,88 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
|
||||||
* X-XSS-Protection: 0
|
* X-XSS-Protection: 0
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param enabled the new value
|
* @param enabled the new value
|
||||||
|
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
|
||||||
|
* instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
setBlock(false);
|
this.headerValue = HeaderValue.DISABLED;
|
||||||
|
}
|
||||||
|
else if (this.headerValue == HeaderValue.DISABLED) {
|
||||||
|
this.headerValue = HeaderValue.ENABLED;
|
||||||
}
|
}
|
||||||
this.enabled = enabled;
|
|
||||||
updateHeaderValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If false, will not specify the mode as blocked. In this instance, any content will
|
* If false, will not specify the mode as blocked. In this instance, any content will
|
||||||
* be attempted to be fixed. If true, the content will be replaced with "#".
|
* be attempted to be fixed. If true, the content will be replaced with "#".
|
||||||
* @param block the new value
|
* @param block the new value
|
||||||
|
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
|
||||||
|
* instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setBlock(boolean block) {
|
public void setBlock(boolean block) {
|
||||||
if (!this.enabled && block) {
|
if (this.headerValue == HeaderValue.DISABLED && block) {
|
||||||
throw new IllegalArgumentException("Cannot set block to true with enabled false");
|
throw new IllegalArgumentException("Cannot set block to true with enabled false");
|
||||||
}
|
}
|
||||||
this.block = block;
|
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
|
||||||
updateHeaderValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateHeaderValue() {
|
/**
|
||||||
if (!this.enabled) {
|
* Sets the value of the X-XSS-PROTECTION header.
|
||||||
this.headerValue = "0";
|
* <p>
|
||||||
return;
|
* If {@link HeaderValue#DISABLED}, will specify that X-XSS-Protection is disabled.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 0
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If {@link HeaderValue#ENABLED}, will contain a value of 1, but will not specify the
|
||||||
|
* mode as blocked. In this instance, any content will be attempted to be fixed. For
|
||||||
|
* example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If {@link HeaderValue#ENABLED_MODE_BLOCK}, will contain a value of 1 and will
|
||||||
|
* specify mode as blocked. The content will be replaced with "#". For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1 ; mode=block
|
||||||
|
* </pre>
|
||||||
|
* @param headerValue the new header value
|
||||||
|
* @throws IllegalArgumentException when headerValue is null
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public void setHeaderValue(HeaderValue headerValue) {
|
||||||
|
Assert.notNull(headerValue, "headerValue cannot be null");
|
||||||
|
this.headerValue = headerValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the x-xss-protection header. One of: "0", "1", "1 ; mode=block"
|
||||||
|
*
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public enum HeaderValue {
|
||||||
|
|
||||||
|
DISABLED("0"), ENABLED("1"), ENABLED_MODE_BLOCK("1; mode=block");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
HeaderValue(String value) {
|
||||||
|
this.value = value;
|
||||||
}
|
}
|
||||||
this.headerValue = "1";
|
|
||||||
if (this.block) {
|
@Override
|
||||||
this.headerValue += "; mode=block";
|
public String toString() {
|
||||||
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -26,24 +26,22 @@ import org.springframework.web.server.ServerWebExchange;
|
||||||
* Add the x-xss-protection header.
|
* Add the x-xss-protection header.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
||||||
|
|
||||||
public static final String X_XSS_PROTECTION = "X-XSS-Protection";
|
public static final String X_XSS_PROTECTION = "X-XSS-Protection";
|
||||||
|
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
private boolean block;
|
|
||||||
|
|
||||||
private ServerHttpHeadersWriter delegate;
|
private ServerHttpHeadersWriter delegate;
|
||||||
|
|
||||||
|
private HeaderValue headerValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*/
|
*/
|
||||||
public XXssProtectionServerHttpHeadersWriter() {
|
public XXssProtectionServerHttpHeadersWriter() {
|
||||||
this.enabled = true;
|
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
|
||||||
this.block = true;
|
|
||||||
updateDelegate();
|
updateDelegate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,12 +71,17 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
|
||||||
* X-XSS-Protection: 0
|
* X-XSS-Protection: 0
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param enabled the new value
|
* @param enabled the new value
|
||||||
|
* @deprecated use
|
||||||
|
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
setBlock(false);
|
this.headerValue = HeaderValue.DISABLED;
|
||||||
|
}
|
||||||
|
else if (this.headerValue == HeaderValue.DISABLED) {
|
||||||
|
this.headerValue = HeaderValue.ENABLED;
|
||||||
}
|
}
|
||||||
this.enabled = enabled;
|
|
||||||
updateDelegate();
|
updateDelegate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,27 +89,78 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
|
||||||
* If false, will not specify the mode as blocked. In this instance, any content will
|
* If false, will not specify the mode as blocked. In this instance, any content will
|
||||||
* be attempted to be fixed. If true, the content will be replaced with "#".
|
* be attempted to be fixed. If true, the content will be replaced with "#".
|
||||||
* @param block the new value
|
* @param block the new value
|
||||||
|
* @deprecated use
|
||||||
|
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setBlock(boolean block) {
|
public void setBlock(boolean block) {
|
||||||
Assert.isTrue(this.enabled || !block, "Cannot set block to true with enabled false");
|
Assert.isTrue(this.headerValue != HeaderValue.DISABLED || !block,
|
||||||
this.block = block;
|
"Cannot set block to true with enabled false");
|
||||||
|
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
|
||||||
updateDelegate();
|
updateDelegate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the X-XSS-PROTECTION header.
|
||||||
|
* <p>
|
||||||
|
* If {@link HeaderValue#DISABLED}, will specify that X-XSS-Protection is disabled.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 0
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If {@link HeaderValue#ENABLED}, will contain a value of 1, but will not specify the
|
||||||
|
* mode as blocked. In this instance, any content will be attempted to be fixed. For
|
||||||
|
* example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If {@link HeaderValue#ENABLED_MODE_BLOCK}, will contain a value of 1 and will
|
||||||
|
* specify mode as blocked. The content will be replaced with "#". For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* X-XSS-Protection: 1 ; mode=block
|
||||||
|
* </pre>
|
||||||
|
* @param headerValue the new headerValue
|
||||||
|
* @throws IllegalArgumentException if headerValue is null
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public void setHeaderValue(HeaderValue headerValue) {
|
||||||
|
Assert.notNull(headerValue, "headerValue cannot be null");
|
||||||
|
this.headerValue = headerValue;
|
||||||
|
updateDelegate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the x-xss-protection header. One of: "0", "1", "1 ; mode=block"
|
||||||
|
*
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
|
* @since 5.8
|
||||||
|
*/
|
||||||
|
public enum HeaderValue {
|
||||||
|
|
||||||
|
DISABLED("0"), ENABLED("1"), ENABLED_MODE_BLOCK("1 ; mode=block");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
HeaderValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void updateDelegate() {
|
private void updateDelegate() {
|
||||||
Builder builder = StaticServerHttpHeadersWriter.builder();
|
Builder builder = StaticServerHttpHeadersWriter.builder();
|
||||||
builder.header(X_XSS_PROTECTION, createHeaderValue());
|
builder.header(X_XSS_PROTECTION, this.headerValue.toString());
|
||||||
this.delegate = builder.build();
|
this.delegate = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createHeaderValue() {
|
|
||||||
if (!this.enabled) {
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
if (!this.block) {
|
|
||||||
return "1";
|
|
||||||
}
|
|
||||||
return "1 ; mode=block";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -94,4 +94,34 @@ public class XXssProtectionHeaderWriterTests {
|
||||||
assertThat(this.response.getHeader(XSS_PROTECTION_HEADER)).isSameAs(value);
|
assertThat(this.response.getHeader(XSS_PROTECTION_HEADER)).isSameAs(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeaderWhenDisabled() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeaderWhenEnabled() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeaderWhenEnabledModeBlock() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("1; mode=block");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setHeaderValueNullThenThrowsIllegalArgumentException() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setHeaderValue(null))
|
||||||
|
.withMessage("headerValue cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,6 +24,7 @@ import org.springframework.mock.web.server.MockServerWebExchange;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
@ -37,6 +38,12 @@ public class XXssProtectionServerHttpHeadersWriterTests {
|
||||||
|
|
||||||
XXssProtectionServerHttpHeadersWriter writer = new XXssProtectionServerHttpHeadersWriter();
|
XXssProtectionServerHttpHeadersWriter writer = new XXssProtectionServerHttpHeadersWriter();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setHeaderValueNullThenThrowsIllegalArgumentException() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setHeaderValue(null))
|
||||||
|
.withMessage("headerValue cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writeHeadersWhenNoHeadersThenWriteHeaders() {
|
public void writeHeadersWhenNoHeadersThenWriteHeaders() {
|
||||||
this.writer.writeHttpHeaders(this.exchange);
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
@ -70,4 +77,29 @@ public class XXssProtectionServerHttpHeadersWriterTests {
|
||||||
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly(headerValue);
|
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly(headerValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenDisabledThenWriteHeaders() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.DISABLED);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
assertThat(this.headers).hasSize(1);
|
||||||
|
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenEnabledThenWriteHeaders() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
assertThat(this.headers).hasSize(1);
|
||||||
|
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenEnabledModeBlockThenWriteHeaders() {
|
||||||
|
this.writer.setHeaderValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
assertThat(this.headers).hasSize(1);
|
||||||
|
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION))
|
||||||
|
.containsOnly("1 ; mode=block");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue