Fix filtered HTTP headers in data binding
Prior to this commit, several common HTTP headers were ignored from the data binding process when collecting property values, in gh-34039 and gh-34182. This commit completes the initial enhancement by ensuring that the default header predicate is also considering cases where constructor binding is applied and the Java type has a lowercase variant of the HTTP header name to filter. Fixes gh-34292
This commit is contained in:
parent
7c5b6f1e1c
commit
d80de043ce
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.reactive.result.method.annotation;
|
package org.springframework.web.reactive.result.method.annotation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -43,11 +44,11 @@ import org.springframework.web.server.ServerWebExchange;
|
||||||
*/
|
*/
|
||||||
public class ExtendedWebExchangeDataBinder extends WebExchangeDataBinder {
|
public class ExtendedWebExchangeDataBinder extends WebExchangeDataBinder {
|
||||||
|
|
||||||
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Accept", "Authorization", "Connection",
|
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("accept", "authorization", "connection",
|
||||||
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade");
|
"cookie", "from", "host", "origin", "priority", "range", "referer", "upgrade");
|
||||||
|
|
||||||
|
|
||||||
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name);
|
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name.toLowerCase(Locale.ROOT));
|
||||||
|
|
||||||
|
|
||||||
public ExtendedWebExchangeDataBinder(@Nullable Object target, String objectName) {
|
public ExtendedWebExchangeDataBinder(@Nullable Object target, String objectName) {
|
||||||
|
|
|
@ -224,7 +224,7 @@ class InitBinderBindingContextTests {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = {"Accept", "Authorization", "Connection",
|
@ValueSource(strings = {"Accept", "Authorization", "Connection",
|
||||||
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade"})
|
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade", "priority"})
|
||||||
void filteredHeaders(String headerName) throws Exception {
|
void filteredHeaders(String headerName) throws Exception {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("/path")
|
MockServerHttpRequest request = MockServerHttpRequest.get("/path")
|
||||||
.header(headerName, "u1")
|
.header(headerName, "u1")
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -39,7 +40,7 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||||
*
|
*
|
||||||
* <p><strong>WARNING</strong>: Data binding can lead to security issues by exposing
|
* <p><strong>WARNING</strong>: Data binding can lead to security issues by exposing
|
||||||
* parts of the object graph that are not meant to be accessed or modified by
|
* parts of the object graph that are not meant to be accessed or modified by
|
||||||
* external clients. Therefore the design and use of data binding should be considered
|
* external clients. Therefore, the design and use of data binding should be considered
|
||||||
* carefully with regard to security. For more details, please refer to the dedicated
|
* carefully with regard to security. For more details, please refer to the dedicated
|
||||||
* sections on data binding for
|
* sections on data binding for
|
||||||
* <a href="https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-initbinder-model-design">Spring Web MVC</a> and
|
* <a href="https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-initbinder-model-design">Spring Web MVC</a> and
|
||||||
|
@ -53,11 +54,11 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||||
*/
|
*/
|
||||||
public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||||
|
|
||||||
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Accept", "Authorization", "Connection",
|
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("accept", "authorization", "connection",
|
||||||
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade");
|
"cookie", "from", "host", "origin", "priority", "range", "referer", "upgrade");
|
||||||
|
|
||||||
|
|
||||||
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name);
|
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name.toLowerCase(Locale.ROOT));
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.testfixture.beans.TestBean;
|
import org.springframework.beans.testfixture.beans.TestBean;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||||
import org.springframework.web.bind.annotation.BindParam;
|
import org.springframework.web.bind.annotation.BindParam;
|
||||||
import org.springframework.web.bind.support.BindParamNameResolver;
|
import org.springframework.web.bind.support.BindParamNameResolver;
|
||||||
|
@ -36,7 +37,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test fixture for {@link ExtendedServletRequestDataBinder}.
|
* Tests for {@link ExtendedServletRequestDataBinder}.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
|
@ -136,6 +137,19 @@ class ExtendedServletRequestDataBinderTests {
|
||||||
assertThat(bean.someIntArray()).isNull();
|
assertThat(bean.someIntArray()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void filteredPriorityHeaderForConstructorBinding() {
|
||||||
|
TestBinder binder = new TestBinder();
|
||||||
|
binder.setTargetType(ResolvableType.forClass(TestTarget.class));
|
||||||
|
request.addHeader("Priority", "u1");
|
||||||
|
|
||||||
|
binder.construct(request);
|
||||||
|
BindingResult result = binder.getBindingResult();
|
||||||
|
TestTarget target = (TestTarget) result.getTarget();
|
||||||
|
|
||||||
|
assertThat(target.priority).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void headerPredicate() {
|
void headerPredicate() {
|
||||||
TestBinder binder = new TestBinder();
|
TestBinder binder = new TestBinder();
|
||||||
|
@ -179,4 +193,14 @@ class ExtendedServletRequestDataBinderTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class TestTarget {
|
||||||
|
|
||||||
|
final String priority;
|
||||||
|
|
||||||
|
public TestTarget(String priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue