Add support for X-Forwarded-For and Forwarded for

See gh-23260, gh-23582
This commit is contained in:
Kirill Serebrennikov
2019-09-06 15:13:34 +03:00
committed by Rossen Stoyanchev
parent ff9daa9377
commit 883ad098f9
7 changed files with 327 additions and 11 deletions

View File

@@ -55,6 +55,8 @@ public class ForwardedHeaderFilterTests {
private static final String X_FORWARDED_PREFIX = "x-forwarded-prefix";
private static final String X_FORWARDED_SSL = "x-forwarded-ssl";
private static final String X_FORWARDED_FOR = "x-forwarded-for";
private static final String FORWARDED = "forwarded";
private final ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
@@ -74,6 +76,114 @@ public class ForwardedHeaderFilterTests {
this.filterChain = new MockFilterChain(new HttpServlet() {});
}
@Test
public void forwardedForEmpty() throws Exception {
this.request.addHeader(X_FORWARDED_FOR, "");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_ADDR);
assertThat(actual.getRemoteHost()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_HOST);
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void forwardedForSingleIdentifier() throws Exception {
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void forwardedForMultipleIdentifiers() throws Exception {
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195, 70.41.3.18, 150.172.238.178");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void standardizedForwardedForIpV4Identifier() throws Exception {
this.request.addHeader(FORWARDED, "for=203.0.113.195");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void standardizedForwardedForIpV6Identifier() throws Exception {
this.request.addHeader(FORWARDED, "for=\"[2001:db8:cafe::17]\"");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("2001:db8:cafe::17");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void standardizedForwardedForUnknownIdentifier() throws Exception {
this.request.addHeader(FORWARDED, "for=unknown");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("unknown");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void standardizedForwardedForObfuscatedIdentifier() throws Exception {
this.request.addHeader(FORWARDED, "for=_abc-12_d.e");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("_abc-12_d.e");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void standardizedForwardedForIpV4IdentifierWithPort() throws Exception {
this.request.addHeader(FORWARDED, "for=\"203.0.113.195:47011\"");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getRemotePort()).isEqualTo(47011);
}
@Test
public void standardizedForwardedForIpV6IdentifierWithPort() throws Exception {
this.request.addHeader(FORWARDED, "For=\"[2001:db8:cafe::17]:47011\"");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("2001:db8:cafe::17");
assertThat(actual.getRemotePort()).isEqualTo(47011);
}
@Test
public void standardizedForwardedForUnknownIdentifierWithPort() throws Exception {
this.request.addHeader(FORWARDED, "for=\"unknown:47011\"");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("unknown");
assertThat(actual.getRemotePort()).isEqualTo(47011);
}
@Test
public void standardizedForwardedForObfuscatedIdentifierWithPort() throws Exception {
this.request.addHeader(FORWARDED, "for=\"_abc-12_d.e:47011\"");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("_abc-12_d.e");
assertThat(actual.getRemotePort()).isEqualTo(47011);
}
@Test
public void standardizedForwardedForMultipleIdentifiers() throws Exception {
this.request.addHeader(FORWARDED, "for=203.0.113.195;proto=http, for=\"[2001:db8:cafe::17]\", for=unknown");
HttpServletRequest actual = filterAndGetWrappedRequest();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getRemotePort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
}
@Test
public void contextPathEmpty() throws Exception {
@@ -224,11 +334,12 @@ public class ForwardedHeaderFilterTests {
@Test
public void shouldFilter() {
testShouldFilter("Forwarded");
testShouldFilter(FORWARDED);
testShouldFilter(X_FORWARDED_HOST);
testShouldFilter(X_FORWARDED_PORT);
testShouldFilter(X_FORWARDED_PROTO);
testShouldFilter(X_FORWARDED_SSL);
testShouldFilter(X_FORWARDED_FOR);
}
private void testShouldFilter(String headerName) {
@@ -249,6 +360,7 @@ public class ForwardedHeaderFilterTests {
this.request.addHeader(X_FORWARDED_HOST, "84.198.58.199");
this.request.addHeader(X_FORWARDED_PORT, "443");
this.request.addHeader("foo", "bar");
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195");
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
HttpServletRequest actual = (HttpServletRequest) this.filterChain.getRequest();
@@ -258,10 +370,12 @@ public class ForwardedHeaderFilterTests {
assertThat(actual.getServerName()).isEqualTo("84.198.58.199");
assertThat(actual.getServerPort()).isEqualTo(443);
assertThat(actual.isSecure()).isTrue();
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("203.0.113.195");
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
assertThat(actual.getHeader("foo")).isEqualTo("bar");
}
@@ -273,6 +387,7 @@ public class ForwardedHeaderFilterTests {
this.request.addHeader(X_FORWARDED_PORT, "443");
this.request.addHeader(X_FORWARDED_SSL, "on");
this.request.addHeader("foo", "bar");
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195");
this.filter.setRemoveOnly(true);
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
@@ -283,11 +398,14 @@ public class ForwardedHeaderFilterTests {
assertThat(actual.getServerName()).isEqualTo("localhost");
assertThat(actual.getServerPort()).isEqualTo(80);
assertThat(actual.isSecure()).isFalse();
assertThat(actual.getRemoteAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_ADDR);
assertThat(actual.getRemoteHost()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_HOST);
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
assertThat(actual.getHeader(X_FORWARDED_SSL)).isNull();
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
assertThat(actual.getHeader("foo")).isEqualTo("bar");
}

View File

@@ -16,7 +16,9 @@
package org.springframework.web.server.adapter;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.jupiter.api.Test;
@@ -35,10 +37,8 @@ public class ForwardedHeaderTransformerTests {
private static final String BASE_URL = "https://example.com/path";
private final ForwardedHeaderTransformer requestMutator = new ForwardedHeaderTransformer();
@Test
void removeOnly() {
this.requestMutator.setRemoveOnly(true);
@@ -50,6 +50,7 @@ public class ForwardedHeaderTransformerTests {
headers.add("X-Forwarded-Proto", "http");
headers.add("X-Forwarded-Prefix", "prefix");
headers.add("X-Forwarded-Ssl", "on");
headers.add("X-Forwarded-For", "203.0.113.195");
ServerHttpRequest request = this.requestMutator.apply(getRequest(headers));
assertForwardedHeadersRemoved(request);
@@ -154,6 +155,55 @@ public class ForwardedHeaderTransformerTests {
assertForwardedHeadersRemoved(request);
}
@Test
public void noForwardedFor() throws URISyntaxException {
HttpHeaders headers = new HttpHeaders();
headers.add("Forwarded", "host=84.198.58.199;proto=https");
InetSocketAddress remoteAddress = new InetSocketAddress("example.client", 47011);
ServerHttpRequest request = MockServerHttpRequest
.method(HttpMethod.GET, new URI("https://example.com/a%20b?q=a%2Bb"))
.remoteAddress(remoteAddress)
.headers(headers)
.build();
request = this.requestMutator.apply(request);
assertThat(request.getRemoteAddress()).isEqualTo(remoteAddress);
}
@Test
public void forwardedFor() throws URISyntaxException {
HttpHeaders headers = new HttpHeaders();
headers.add("Forwarded", "for=\"203.0.113.195:4711\";host=84.198.58.199;proto=https");
InetSocketAddress remoteAddress = new InetSocketAddress("example.client", 47011);
ServerHttpRequest request = MockServerHttpRequest
.method(HttpMethod.GET, new URI("https://example.com/a%20b?q=a%2Bb"))
.remoteAddress(remoteAddress)
.headers(headers)
.build();
request = this.requestMutator.apply(request);
assertThat(request.getRemoteAddress().getHostName()).isEqualTo("203.0.113.195");
assertThat(request.getRemoteAddress().getPort()).isEqualTo(4711);
}
@Test
public void xForwardedFor() throws URISyntaxException {
HttpHeaders headers = new HttpHeaders();
headers.add("x-forwarded-for", "203.0.113.195, 70.41.3.18, 150.172.238.178");
ServerHttpRequest request = MockServerHttpRequest
.method(HttpMethod.GET, new URI("https://example.com/a%20b?q=a%2Bb"))
.headers(headers)
.build();
request = this.requestMutator.apply(request);
assertThat(request.getRemoteAddress().getHostName()).isEqualTo("203.0.113.195");
}
private MockServerHttpRequest getRequest(HttpHeaders headers) {
return MockServerHttpRequest.get(BASE_URL).headers(headers).build();