Merge branch '5.8.x'
This commit is contained in:
+69
-23
@@ -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");
|
||||
* 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 org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* 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 boolean enabled;
|
||||
|
||||
private boolean block;
|
||||
|
||||
private String headerValue;
|
||||
private HeaderValue headerValue;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*/
|
||||
public XXssProtectionHeaderWriter() {
|
||||
this.enabled = true;
|
||||
this.block = true;
|
||||
updateHeaderValue();
|
||||
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||
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
|
||||
* </pre>
|
||||
* @param enabled the new value
|
||||
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setEnabled(boolean 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
|
||||
* be attempted to be fixed. If true, the content will be replaced with "#".
|
||||
* @param block the new value
|
||||
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
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");
|
||||
}
|
||||
this.block = block;
|
||||
updateHeaderValue();
|
||||
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
|
||||
}
|
||||
|
||||
private void updateHeaderValue() {
|
||||
if (!this.enabled) {
|
||||
this.headerValue = "0";
|
||||
return;
|
||||
/**
|
||||
* 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 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) {
|
||||
this.headerValue += "; mode=block";
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+76
-22
@@ -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");
|
||||
* 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.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Daniel Garnier-Moiroux
|
||||
* @since 5.0
|
||||
*/
|
||||
public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
||||
|
||||
public static final String X_XSS_PROTECTION = "X-XSS-Protection";
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private boolean block;
|
||||
|
||||
private ServerHttpHeadersWriter delegate;
|
||||
|
||||
private HeaderValue headerValue;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*/
|
||||
public XXssProtectionServerHttpHeadersWriter() {
|
||||
this.enabled = true;
|
||||
this.block = true;
|
||||
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
|
||||
updateDelegate();
|
||||
}
|
||||
|
||||
@@ -73,12 +71,17 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
|
||||
* X-XSS-Protection: 0
|
||||
* </pre>
|
||||
* @param enabled the new value
|
||||
* @deprecated use
|
||||
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setEnabled(boolean enabled) {
|
||||
if (!enabled) {
|
||||
setBlock(false);
|
||||
this.headerValue = HeaderValue.DISABLED;
|
||||
}
|
||||
else if (this.headerValue == HeaderValue.DISABLED) {
|
||||
this.headerValue = HeaderValue.ENABLED;
|
||||
}
|
||||
this.enabled = enabled;
|
||||
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
|
||||
* be attempted to be fixed. If true, the content will be replaced with "#".
|
||||
* @param block the new value
|
||||
* @deprecated use
|
||||
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setBlock(boolean block) {
|
||||
Assert.isTrue(this.enabled || !block, "Cannot set block to true with enabled false");
|
||||
this.block = block;
|
||||
Assert.isTrue(this.headerValue != HeaderValue.DISABLED || !block,
|
||||
"Cannot set block to true with enabled false");
|
||||
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
|
||||
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() {
|
||||
Builder builder = StaticServerHttpHeadersWriter.builder();
|
||||
builder.header(X_XSS_PROTECTION, createHeaderValue());
|
||||
builder.header(X_XSS_PROTECTION, this.headerValue.toString());
|
||||
this.delegate = builder.build();
|
||||
}
|
||||
|
||||
private String createHeaderValue() {
|
||||
if (!this.enabled) {
|
||||
return "0";
|
||||
}
|
||||
if (!this.block) {
|
||||
return "1";
|
||||
}
|
||||
return "1 ; mode=block";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-1
@@ -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");
|
||||
* 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);
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+33
-1
@@ -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");
|
||||
* 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -37,6 +38,12 @@ public class XXssProtectionServerHttpHeadersWriterTests {
|
||||
|
||||
XXssProtectionServerHttpHeadersWriter writer = new XXssProtectionServerHttpHeadersWriter();
|
||||
|
||||
@Test
|
||||
void setHeaderValueNullThenThrowsIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setHeaderValue(null))
|
||||
.withMessage("headerValue cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeHeadersWhenNoHeadersThenWriteHeaders() {
|
||||
this.writer.writeHttpHeaders(this.exchange);
|
||||
@@ -70,4 +77,29 @@ public class XXssProtectionServerHttpHeadersWriterTests {
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user