I'm working on applications that requires access to X-Forwarded-*
headers, unfortunately Spring Boot 2.2 changed the way it auto-configures itself, and those are not anymore available in the custom code unless you dive in to understand the change.
In spring boot 2.1 when the server.use-forward-headers
property was not set, Spring Boot did not configure the org.apache.catalina.valves.RemoteIpValve
from Tomcat when the application was running within a cloud provider environment.
* TomcatWebServerFactoryCustomizer in 2.1.x
This changed in Spring Boot 2.2, when the new property server.forward-headers-strategy
is not configured, i.e. it's value is org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeadersStrategy.NONE
, then the new code always tries to detect a cloud provider via org.springframework.boot.cloud.CloudPlatform.getActive(Environment)
(using the environment variables). In particular when Kubernetes is detected it configures the org.apache.catalina.valves.RemoteIpValve
(which the same as if server.forward-headers-strategy
property was set to org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeadersStrategy.NATIVE
).
* TomcatWebServerFactoryCustomizer in 2.2.x
* CloudPlatform in 2.2.x
This Tomcat Valve has a side effect : this class replaces the value in the corresponding attribute of javax.servlet.ServletRequest
and removes the X-Forwarded-*
header. On the other hand switching server.forward-headers-strategy
to org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeadersStrategy.FRAMEWORK
to prevent the auto-detection of the cloud platform does not help as well. This time it's the ForwardedHeaderFilter
that has the same kind of side effect : this filter map all X-Forwarded-*
headers to javax.servlet.ServletRequest
attributes but X-Forwarded-For.
- Filters forward headers
- customize tomcat behind a proxy server
- deprecations-in-spring-boot-22
- Add 'server.remove-forward-headers' options #11525
- Add support for X-Forwarded-Host using Tomcat's new RemoteIpValve hostHeader attribute #18233
This is unfortunate as this isn't explicitly documented, and there's no way to disable this behavior by configuration. While I understand the value of the change as a whole, I believe this particular scenario could be seen as a regression that was introduced.
Currently the only hack to prevent this is to register a dummy of ForwardHeaderFilter
@Bean
public ForwardedHeaderFilter disabledForwardedHeaderFilter() {
return new ForwardedHeaderFilter() {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return true;
}
};
}
What I think is missing in the current code 2.2.1.RELEASE are these things
* org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeadersStrategy.FORCE_NONE
* allow to configure ForwardHeaderFilter
to not remove the headers
On another related topic, discovering this behavior and testing it (with unit test) was not straightforward. For example the code of CloudPlatform
explicitly asks for StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME
which obstructs the usual usage of the annotation @SpringBootTest(properties = {})
Comment From: kampka
FORCE_NONE
is not a great name. NONE
should simply do what the documentation claims it does: Ignore X-Forwarded-* headers.
What's required here is a new value like CLOUD_NATIVE
which is much more self-explanatory.
Comment From: bric3
I totally agree !
I wasn't sure what was the expected behavior of NONE
, should it detect automatically cloud provider ? Or simply because we don't want to break backward compatibilIty.
But if that's ok to keep NONE
and I troduce something more explicit I'm all for it.