Allows to override default set of sensitive headers in WebFlux ProxyExchange
Fixes gh-1800 Fixes gh-1974
This commit is contained in:
committed by
spencergibb
parent
b528c9dfc7
commit
894402aab3
@@ -32,6 +32,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
@@ -215,6 +216,8 @@ public class ProxyExchange<T> {
|
||||
if (this.sensitive == null) {
|
||||
this.sensitive = new HashSet<>();
|
||||
}
|
||||
|
||||
this.sensitive.clear();
|
||||
for (String name : names) {
|
||||
this.sensitive.add(name.toLowerCase());
|
||||
}
|
||||
@@ -342,20 +345,19 @@ public class ProxyExchange<T> {
|
||||
}
|
||||
|
||||
private BodyBuilder headers(BodyBuilder builder) {
|
||||
Set<String> sensitive = this.sensitive;
|
||||
if (sensitive == null) {
|
||||
sensitive = DEFAULT_SENSITIVE;
|
||||
}
|
||||
proxy();
|
||||
for (String name : headers.keySet()) {
|
||||
if (sensitive.contains(name.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
for (String name : filterHeaderKeys(headers)) {
|
||||
builder.header(name, headers.get(name).toArray(new String[0]));
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private Set<String> filterHeaderKeys(HttpHeaders headers) {
|
||||
final Set<String> sensitiveHeaders = this.sensitive != null ? this.sensitive : DEFAULT_SENSITIVE;
|
||||
return headers.keySet().stream().filter(header -> !sensitiveHeaders.contains(header.toLowerCase()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void proxy() {
|
||||
try {
|
||||
URI uri = new URI(webRequest.getNativeRequest(HttpServletRequest.class).getRequestURL().toString());
|
||||
|
||||
@@ -236,6 +236,29 @@ public class ProductionConfigurationTests {
|
||||
assertThat(deleteResponse.getBody().get("deleted")).isEqualToComparingFieldByField(foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "Duplicates", "unchecked" })
|
||||
public void testSensitiveHeadersOverride() throws Exception {
|
||||
Map<String, List<String>> headers = rest
|
||||
.exchange(
|
||||
RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
|
||||
.header("foo", "bar").header("abc", "xyz").header("cookie", "monster").build(),
|
||||
Map.class)
|
||||
.getBody();
|
||||
assertThat(headers).doesNotContainKey("foo").doesNotContainKey("hello").containsKeys("bar", "abc");
|
||||
|
||||
assertThat(headers.get("cookie")).containsOnly("monster");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSensitiveHeadersDefault() throws Exception {
|
||||
Map<String, List<String>> headers = rest.exchange(RequestEntity
|
||||
.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/sensitive-headers-default"))
|
||||
.header("cookie", "monster").build(), Map.class).getBody();
|
||||
|
||||
assertThat(headers).doesNotContainKey("cookie");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "Duplicates", "unchecked" })
|
||||
public void headers() throws Exception {
|
||||
@@ -406,8 +429,16 @@ public class ProductionConfigurationTests {
|
||||
@GetMapping("/proxy/headers")
|
||||
@SuppressWarnings("Duplicates")
|
||||
public ResponseEntity<Map<String, List<String>>> headers(ProxyExchange<Map<String, List<String>>> proxy) {
|
||||
proxy.sensitive("foo");
|
||||
proxy.sensitive("hello");
|
||||
proxy.sensitive("foo", "hello");
|
||||
proxy.header("bar", "hello");
|
||||
proxy.header("abc", "123");
|
||||
proxy.header("hello", "world");
|
||||
return proxy.uri(home.toString() + "/headers").get();
|
||||
}
|
||||
|
||||
@GetMapping("/proxy/sensitive-headers-default")
|
||||
public ResponseEntity<Map<String, List<String>>> defaultSensitiveHeaders(
|
||||
ProxyExchange<Map<String, List<String>>> proxy) {
|
||||
proxy.header("bar", "hello");
|
||||
proxy.header("abc", "123");
|
||||
proxy.header("hello", "world");
|
||||
|
||||
@@ -140,8 +140,6 @@ public class ProxyExchange<T> {
|
||||
this.bindingContext = bindingContext;
|
||||
this.responseType = type;
|
||||
this.rest = rest;
|
||||
this.sensitive = new HashSet<>(DEFAULT_SENSITIVE.size());
|
||||
this.sensitive.addAll(DEFAULT_SENSITIVE);
|
||||
this.httpMethod = exchange.getRequest().getMethod();
|
||||
}
|
||||
|
||||
@@ -206,6 +204,8 @@ public class ProxyExchange<T> {
|
||||
if (this.sensitive == null) {
|
||||
this.sensitive = new HashSet<>();
|
||||
}
|
||||
|
||||
this.sensitive.clear();
|
||||
for (String name : names) {
|
||||
this.sensitive.add(name.toLowerCase());
|
||||
}
|
||||
@@ -376,7 +376,8 @@ public class ProxyExchange<T> {
|
||||
}
|
||||
|
||||
private Set<String> filterHeaderKeys(HttpHeaders headers) {
|
||||
return headers.keySet().stream().filter(header -> !sensitive.contains(header.toLowerCase()))
|
||||
final Set<String> sensitiveHeaders = this.sensitive != null ? this.sensitive : DEFAULT_SENSITIVE;
|
||||
return headers.keySet().stream().filter(header -> !sensitiveHeaders.contains(header.toLowerCase()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,29 @@ public class ProductionConfigurationTests {
|
||||
.isEqualTo("host=localhost:" + port + ";foobar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "Duplicates", "unchecked" })
|
||||
public void testSensitiveHeadersOverride() throws Exception {
|
||||
Map<String, List<String>> headers = rest
|
||||
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
|
||||
.header("foo", "bar").header("abc", "xyz").header("cookie", "monster").build(), Map.class)
|
||||
.getBody();
|
||||
assertThat(headers).doesNotContainKey("foo").doesNotContainKey("hello").containsKeys("bar", "abc");
|
||||
|
||||
assertThat(headers.get("cookie")).containsOnly("monster");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSensitiveHeadersDefault() throws Exception {
|
||||
Map<String, List<String>> headers = rest
|
||||
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/sensitive-headers-default"))
|
||||
.header("cookie", "monster")
|
||||
.build(), Map.class)
|
||||
.getBody();
|
||||
|
||||
assertThat(headers).doesNotContainKey("cookie");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "Duplicates", "unchecked" })
|
||||
public void headers() throws Exception {
|
||||
@@ -317,8 +340,16 @@ public class ProductionConfigurationTests {
|
||||
@GetMapping("/proxy/headers")
|
||||
public Mono<ResponseEntity<Map<String, List<String>>>> headers(
|
||||
ProxyExchange<Map<String, List<String>>> proxy) {
|
||||
proxy.sensitive("foo");
|
||||
proxy.sensitive("hello");
|
||||
proxy.sensitive("foo", "hello");
|
||||
proxy.header("bar", "hello");
|
||||
proxy.header("abc", "123");
|
||||
proxy.header("hello", "world");
|
||||
return proxy.uri(home.toString() + "/headers").get();
|
||||
}
|
||||
|
||||
@GetMapping("/proxy/sensitive-headers-default")
|
||||
public Mono<ResponseEntity<Map<String, List<String>>>> defaultSensitiveHeaders(
|
||||
ProxyExchange<Map<String, List<String>>> proxy) {
|
||||
proxy.header("bar", "hello");
|
||||
proxy.header("abc", "123");
|
||||
proxy.header("hello", "world");
|
||||
|
||||
Reference in New Issue
Block a user