Remove individual detection of forwarded headers

This commit removes all places where forwarded headers are checked
implicitly, on an ad-hoc basis.

ForwardedHeaderFilter is expected to be used instead providing
centralized control over using or discarding such headers.

Issue: SPR-16668
This commit is contained in:
Rossen Stoyanchev
2018-05-11 09:31:39 -04:00
parent 82a8e42ff9
commit 4da43de7e1
14 changed files with 251 additions and 299 deletions

View File

@@ -16,6 +16,8 @@
package org.springframework.web.cors.reactive;
import java.net.URI;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -49,18 +51,16 @@ public abstract class CorsUtils {
}
/**
* Check if the request is a same-origin one, based on {@code Origin}, {@code Host},
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
* @code X-Forwarded-Port} headers.
* Check if the request is a same-origin one, based on {@code Origin}, and
* {@code Host} headers.
*
* <p><strong>Note:</strong> as of 5.1 this method ignores
* {@code "Forwarded"} and {@code "X-Forwarded-*"} headers that specify the
* client-originated address. Consider using the {@code ForwardedHeaderFilter}
* to extract and use, or to discard such headers.
*
* @return {@code true} if the request is a same-origin one, {@code false} in case
* of a cross-origin request
* <p><strong>Note:</strong> this method uses values from "Forwarded"
* (<a href="http://tools.ietf.org/html/rfc7239">RFC 7239</a>),
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" headers,
* if present, in order to reflect the client-originated address.
* Consider using the {@code ForwardedHeaderFilter} in order to choose from a
* central place whether to extract and use, or to discard such headers.
* See the Spring Framework reference for more on this filter.
*/
public static boolean isSameOrigin(ServerHttpRequest request) {
String origin = request.getHeaders().getOrigin();
@@ -68,9 +68,9 @@ public abstract class CorsUtils {
return true;
}
UriComponents actualUrl = UriComponentsBuilder.fromHttpRequest(request).build();
String actualHost = actualUrl.getHost();
int actualPort = getPort(actualUrl.getScheme(), actualUrl.getPort());
URI uri = request.getURI();
String actualHost = uri.getHost();
int actualPort = getPort(uri.getScheme(), uri.getPort());
Assert.notNull(actualHost, "Actual request host must not be null");
Assert.isTrue(actualPort != -1, "Actual request port must not be undefined");

View File

@@ -18,11 +18,10 @@ package org.springframework.web.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import javax.servlet.ServletContext;
@@ -138,16 +137,6 @@ public abstract class WebUtils {
/** Key for the mutex session attribute */
public static final String SESSION_MUTEX_ATTRIBUTE = WebUtils.class.getName() + ".MUTEX";
private static final Set<String> FORWARDED_HEADER_NAMES = new LinkedHashSet<>(5);
static {
FORWARDED_HEADER_NAMES.add("Forwarded");
FORWARDED_HEADER_NAMES.add("X-Forwarded-Host");
FORWARDED_HEADER_NAMES.add("X-Forwarded-Port");
FORWARDED_HEADER_NAMES.add("X-Forwarded-Proto");
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
}
/**
* Set a system property to the web application root directory.
@@ -677,13 +666,12 @@ public abstract class WebUtils {
* Check the given request origin against a list of allowed origins.
* A list containing "*" means that all origins are allowed.
* An empty list means only same origin is allowed.
* <p><strong>Note:</strong> this method may use values from "Forwarded"
* (<a href="http://tools.ietf.org/html/rfc7239">RFC 7239</a>),
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" headers,
* if present, in order to reflect the client-originated address.
* Consider using the {@code ForwardedHeaderFilter} in order to choose from a
* central place whether to extract and use, or to discard such headers.
* See the Spring Framework reference for more on this filter.
*
* <p><strong>Note:</strong> as of 5.1 this method ignores
* {@code "Forwarded"} and {@code "X-Forwarded-*"} headers that specify the
* client-originated address. Consider using the {@code ForwardedHeaderFilter}
* to extract and use, or to discard such headers.
*
* @return {@code true} if the request origin is valid, {@code false} otherwise
* @since 4.1.5
* @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454: The Web Origin Concept</a>
@@ -708,13 +696,12 @@ public abstract class WebUtils {
* Check if the request is a same-origin one, based on {@code Origin}, {@code Host},
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
* @code X-Forwarded-Port} headers.
* <p><strong>Note:</strong> this method uses values from "Forwarded"
* (<a href="http://tools.ietf.org/html/rfc7239">RFC 7239</a>),
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" headers,
* if present, in order to reflect the client-originated address.
* Consider using the {@code ForwardedHeaderFilter} in order to choose from a
* central place whether to extract and use, or to discard such headers.
* See the Spring Framework reference for more on this filter.
*
* <p><strong>Note:</strong> as of 5.1 this method ignores
* {@code "Forwarded"} and {@code "X-Forwarded-*"} headers that specify the
* client-originated address. Consider using the {@code ForwardedHeaderFilter}
* to extract and use, or to discard such headers.
* @return {@code true} if the request is a same-origin one, {@code false} in case
* of cross-origin request
* @since 4.2
@@ -735,21 +722,12 @@ public abstract class WebUtils {
scheme = servletRequest.getScheme();
host = servletRequest.getServerName();
port = servletRequest.getServerPort();
if (containsForwardedHeaders(servletRequest)) {
UriComponents actualUrl = new UriComponentsBuilder()
.scheme(scheme).host(host).port(port)
.adaptFromForwardedHeaders(headers)
.build();
scheme = actualUrl.getScheme();
host = actualUrl.getHost();
port = actualUrl.getPort();
}
}
else {
UriComponents actualUrl = UriComponentsBuilder.fromHttpRequest(request).build();
scheme = actualUrl.getScheme();
host = actualUrl.getHost();
port = actualUrl.getPort();
URI uri = request.getURI();
scheme = uri.getScheme();
host = uri.getHost();
port = uri.getPort();
}
UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build();
@@ -757,15 +735,6 @@ public abstract class WebUtils {
getPort(scheme, port) == getPort(originUrl.getScheme(), originUrl.getPort()));
}
private static boolean containsForwardedHeaders(HttpServletRequest request) {
for (String headerName : FORWARDED_HEADER_NAMES) {
if (request.getHeader(headerName) != null) {
return true;
}
}
return false;
}
private static int getPort(@Nullable String scheme, int port) {
if (port == -1) {
if ("http".equals(scheme) || "ws".equals(scheme)) {