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
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user