Refine forwarded protocol support

This commit refines forwarded protocol support in order to support
proxies that only set "X-Forwarded-Proto" header and not
"X-Forwarded-Port" by performing a reset of the port in such case.

"Forwarded" header support has been updated accordingly since it
also supports similar use case, as described in SPR-15504.

Issue: SPR-16262
This commit is contained in:
sdeleuze
2017-12-26 17:55:26 +01:00
parent 30c0616384
commit c326e44488
6 changed files with 155 additions and 13 deletions

View File

@@ -51,7 +51,8 @@ public abstract class CorsUtils {
/**
* Check if the request is a same-origin one, based on {@code Origin}, {@code Host},
* {@code Forwarded} and {@code X-Forwarded-Host} headers.
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
* @code X-Forwarded-Port} headers.
* @return {@code true} if the request is a same-origin one, {@code false} in case
* of cross-origin request.
*/

View File

@@ -53,6 +53,7 @@ import org.springframework.web.util.HierarchicalUriComponents.PathComponent;
* @author Phillip Webb
* @author Oliver Gierke
* @author Brian Clozel
* @author Sebastien Deleuze
* @since 3.1
* @see #newInstance()
* @see #fromPath(String)
@@ -731,16 +732,23 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
String forwardedHeader = headers.getFirst("Forwarded");
if (StringUtils.hasText(forwardedHeader)) {
String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0];
Matcher matcher = FORWARDED_HOST_PATTERN.matcher(forwardedToUse);
Matcher matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse);
if (matcher.find()) {
scheme(matcher.group(1).trim());
port(null);
}
matcher = FORWARDED_HOST_PATTERN.matcher(forwardedToUse);
if (matcher.find()) {
adaptForwardedHost(matcher.group(1).trim());
}
matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse);
if (matcher.find()) {
scheme(matcher.group(1).trim());
}
}
else {
String protocolHeader = headers.getFirst("X-Forwarded-Proto");
if (StringUtils.hasText(protocolHeader)) {
scheme(StringUtils.tokenizeToStringArray(protocolHeader, ",")[0]);
port(null);
}
String hostHeader = headers.getFirst("X-Forwarded-Host");
if (StringUtils.hasText(hostHeader)) {
adaptForwardedHost(StringUtils.tokenizeToStringArray(hostHeader, ",")[0]);
@@ -750,16 +758,11 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
if (StringUtils.hasText(portHeader)) {
port(Integer.parseInt(StringUtils.tokenizeToStringArray(portHeader, ",")[0]));
}
String protocolHeader = headers.getFirst("X-Forwarded-Proto");
if (StringUtils.hasText(protocolHeader)) {
scheme(StringUtils.tokenizeToStringArray(protocolHeader, ",")[0]);
}
}
if ((this.scheme != null) && ((this.scheme.equals("http") && "80".equals(this.port)) ||
(this.scheme.equals("https") && "443".equals(this.port)))) {
this.port = null;
port(null);
}
return this;

View File

@@ -686,7 +686,8 @@ public abstract class WebUtils {
/**
* Check if the request is a same-origin one, based on {@code Origin}, {@code Host},
* {@code Forwarded} and {@code X-Forwarded-Host} headers.
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
* @code X-Forwarded-Port} headers.
* @return {@code true} if the request is a same-origin one, {@code false} in case
* of cross-origin request
* @since 4.2