Configure ForwardedHeaderFilter with Tomcat's use relative redirects

Previously, when Tomcat was configured to use relative redirects
and the ForwardedHeaderFilter is in use, the filter would ignore
the use of the relative redirects.

This commit corrects this misalignment by applying Tomcat's use
relative redirects setting to the filter, but only when Tomcat is
being used as the servlet container.

See gh-29333
pull/29762/head
Guirong Hu 3 years ago committed by Andy Wilkinson
parent 59799c81b0
commit cec69feb95

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -85,15 +85,33 @@ public class ServletWebServerFactoryAutoConfiguration {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
static class ForwardedHeaderFilterConfiguration {
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
public FilterRegistrationBean<ForwardedHeaderFilter> tomcatForwardedHeaderFilter(
ServerProperties serverProperties) {
return createForwardedHeaderFilter(serverProperties.getTomcat().isUseRelativeRedirects());
}
@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
public FilterRegistrationBean<ForwardedHeaderFilter> defaultForwardedHeaderFilter() {
return createForwardedHeaderFilter(false);
}
private FilterRegistrationBean<ForwardedHeaderFilter> createForwardedHeaderFilter(boolean relativeRedirects) {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
filter.setRelativeRedirects(relativeRedirects);
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
/**

@ -57,6 +57,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.filter.ForwardedHeaderFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
@ -368,6 +369,36 @@ class ServletWebServerFactoryAutoConfigurationTests {
.run((context) -> assertThat(context).hasSingleBean(FilterRegistrationBean.class));
}
@Test
void relativeRedirectsShouldBeEnabledWhenUsingTomcatContainerAndUseRelativeRedirects() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
.withPropertyValues("server.forward-headers-strategy=framework",
"server.tomcat.use-relative-redirects=true");
runner.run((context) -> {
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
Boolean relativeRedirects = (Boolean) ReflectionTestUtils.getField(filter, "relativeRedirects");
assertThat(relativeRedirects).isTrue();
});
}
@Test
void relativeRedirectsShouldNotBeEnabledWhenNotUsingTomcatContainer() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withClassLoader(new FilteredClassLoader(Tomcat.class))
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
.withPropertyValues("server.forward-headers-strategy=framework");
runner.run((context) -> {
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
Boolean relativeRedirects = (Boolean) ReflectionTestUtils.getField(filter, "relativeRedirects");
assertThat(relativeRedirects).isFalse();
});
}
private ContextConsumer<AssertableWebApplicationContext> verifyContext() {
return this::verifyContext;
}

Loading…
Cancel
Save