From e10eb0707361dfa74590145b2fdd3360b5762da7 Mon Sep 17 00:00:00 2001 From: markt Date: Mon, 9 May 2011 12:32:49 +0000 Subject: [PATCH] Port RemoteIpValve changes to RemoteIpFilter git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1100988 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/catalina/filters/RemoteIpFilter.java | 90 +++++++++++++++++++++- webapps/docs/changelog.xml | 6 +- webapps/docs/config/filter.xml | 29 +++++-- 3 files changed, 111 insertions(+), 14 deletions(-) diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java index da2a1bed5..34278990b 100644 --- a/java/org/apache/catalina/filters/RemoteIpFilter.java +++ b/java/org/apache/catalina/filters/RemoteIpFilter.java @@ -454,6 +454,8 @@ public class RemoteIpFilter implements Filter { protected Map> headers; + protected int localPort; + protected String remoteAddr; protected String remoteHost; @@ -463,9 +465,10 @@ public class RemoteIpFilter implements Filter { protected boolean secure; protected int serverPort; - + public XForwardedRequest(HttpServletRequest request) { super(request); + this.localPort = request.getLocalPort(); this.remoteAddr = request.getRemoteAddr(); this.remoteHost = request.getRemoteHost(); this.scheme = request.getScheme(); @@ -543,6 +546,11 @@ public class RemoteIpFilter implements Filter { } @Override + public int getLocalPort() { + return localPort; + } + + @Override public String getRemoteAddr() { return this.remoteAddr; } @@ -585,6 +593,10 @@ public class RemoteIpFilter implements Filter { } + public void setLocalPort(int localPort) { + this.localPort = localPort; + } + public void setRemoteAddr(String remoteAddr) { this.remoteAddr = remoteAddr; } @@ -626,6 +638,10 @@ public class RemoteIpFilter implements Filter { protected static final String PROTOCOL_HEADER_HTTPS_VALUE_PARAMETER = "protocolHeaderHttpsValue"; + protected static final String PORT_HEADER_PARAMETER = "portHeader"; + + protected static final String CHANGE_LOCAL_PORT_PARAMETER = "changeLocalPort"; + protected static final String PROXIES_HEADER_PARAMETER = "proxiesHeader"; protected static final String REMOTE_IP_HEADER_PARAMETER = "remoteIpHeader"; @@ -688,6 +704,10 @@ public class RemoteIpFilter implements Filter { private String protocolHeaderHttpsValue = "https"; + private String portHeader = null; + + private boolean changeLocalPort = false; + /** * @see #setProxiesHeader(String) */ @@ -780,11 +800,11 @@ public class RemoteIpFilter implements Filter { } else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) { xRequest.setSecure(true); xRequest.setScheme("https"); - xRequest.setServerPort(httpsServerPort); + setPorts(xRequest, httpsServerPort); } else { xRequest.setSecure(false); xRequest.setScheme("http"); - xRequest.setServerPort(httpServerPort); + setPorts(xRequest, httpServerPort); } } @@ -819,6 +839,25 @@ public class RemoteIpFilter implements Filter { } + private void setPorts(XForwardedRequest xrequest, int defaultPort) { + int port = defaultPort; + if (getPortHeader() != null) { + String portHeaderValue = xrequest.getHeader(getPortHeader()); + if (portHeaderValue != null) { + try { + port = Integer.parseInt(portHeaderValue); + } catch (NumberFormatException nfe) { + log.debug("Invalid port value [" + portHeaderValue + + "] provided in header [" + getPortHeader() + "]"); + } + } + } + xrequest.setServerPort(port); + if (isChangeLocalPort()) { + xrequest.setLocalPort(port); + } + } + /** * Wrap the incoming request in a {@link XForwardedRequest} if the http header x-forwareded-for is not empty. */ @@ -831,6 +870,10 @@ public class RemoteIpFilter implements Filter { } } + public boolean isChangeLocalPort() { + return changeLocalPort; + } + public int getHttpsServerPort() { return httpsServerPort; } @@ -843,6 +886,10 @@ public class RemoteIpFilter implements Filter { return protocolHeader; } + public String getPortHeader() { + return portHeader; + } + public String getProtocolHeaderHttpsValue() { return protocolHeaderHttpsValue; } @@ -882,6 +929,14 @@ public class RemoteIpFilter implements Filter { setProtocolHeaderHttpsValue(filterConfig.getInitParameter(PROTOCOL_HEADER_HTTPS_VALUE_PARAMETER)); } + if (filterConfig.getInitParameter(PORT_HEADER_PARAMETER) != null) { + setPortHeader(filterConfig.getInitParameter(PORT_HEADER_PARAMETER)); + } + + if (filterConfig.getInitParameter(CHANGE_LOCAL_PORT_PARAMETER) != null) { + setChangeLocalPort(Boolean.parseBoolean(filterConfig.getInitParameter(CHANGE_LOCAL_PORT_PARAMETER))); + } + if (filterConfig.getInitParameter(PROXIES_HEADER_PARAMETER) != null) { setProxiesHeader(filterConfig.getInitParameter(PROXIES_HEADER_PARAMETER)); } @@ -913,6 +968,21 @@ public class RemoteIpFilter implements Filter { /** *

+ * If true, the return values for both {@link + * ServletRequest#getLocalPort()} and {@link ServletRequest#getServerPort()} + * wil be modified by this Filter rather than just + * {@link ServletRequest#getServerPort()}. + *

+ *

+ * Default value : false + *

+ */ + public void setChangeLocalPort(boolean changeLocalPort) { + this.changeLocalPort = changeLocalPort; + } + + /** + *

* Server Port value if the {@link #protocolHeader} indicates HTTP (i.e. {@link #protocolHeader} is not null and * has a value different of {@link #protocolHeaderHttpsValue}). *

@@ -954,6 +1024,20 @@ public class RemoteIpFilter implements Filter { /** *

+ * Header that holds the incoming port, usally named + * X-Forwarded-Port. If null, + * {@link #httpServerPort} or {@link #httpsServerPort} will be used. + *

+ *

+ * Default value : null + *

+ */ + public void setPortHeader(String portHeader) { + this.portHeader = portHeader; + } + + /** + *

* Header that holds the incoming protocol, usally named X-Forwarded-Proto. If null, request.scheme and * request.secure will not be modified. *

diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 7c62d243e..05911d461 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -66,10 +66,10 @@ StandardWrapper. (markt) - Provide additional configuration options for the RemoteIpValve to allow - greater control over the values returned by + Provide additional configuration options for the RemoteIpValve and + RemoteIpFilter to allow greater control over the values returned by ServletRequest#getServerPort() and ServletRequest#getLocalPort() when - using this valve. (markt) + Tomcat is behind a reverse proxy. (markt) diff --git a/webapps/docs/config/filter.xml b/webapps/docs/config/filter.xml index 1ccc011aa..692ae434c 100644 --- a/webapps/docs/config/filter.xml +++ b/webapps/docs/config/filter.xml @@ -990,6 +990,12 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ default of null is used.

+ +

Name of the HTTP Header read by this valve that holds the port + used by the client to connect to the proxy. If not specified, the + default of null is used.

+
+

Value of the protocolHeader to indicate that it is an HTTPS request. If not specified, the default of https is @@ -997,17 +1003,24 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ -

Value returned by ServletRequest.getServerPort() - when the protocolHeader indicates http - protocol. If not specified, the default of 80 is - used.

+

Value returned by ServletRequest.getServerPort() + when the protocolHeader indicates http + protocol and no portHeader is present. If not + specified, the default of 80 is used.

-

Value returned by ServletRequest.getServerPort() - when the protocolHeader indicates https - protocol. If not specified, the default of 443 is - used.

+

Value returned by ServletRequest.getServerPort() + when the protocolHeader indicates https + protocol and no portHeader is present. If not + specified, the default of 443 is used.

+
+ + +

If true, the value returned by + ServletRequest.getLocalPort() and + ServletRequest.getServerPort() is modified by the this + filter. If not specified, the default of false is used.

-- 2.11.0