Skip to content

Commit 8685893

Browse files
Rob Winchwilkinsona
Rob Winch
authored andcommitted
Ensure that Spring Security Filter's order is configured
This commit ensures that even when a user specifies a WebSecurityConfiguration that the order of Spring Security's Filter is still configured. Closes gh-3824 See gh-3703
1 parent 9dec097 commit 8685893

File tree

4 files changed

+117
-17
lines changed

4 files changed

+117
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.boot.autoconfigure.security;
17+
18+
import javax.servlet.Filter;
19+
20+
import org.springframework.beans.factory.annotation.Qualifier;
21+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
24+
import org.springframework.boot.context.embedded.FilterRegistrationBean;
25+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
29+
30+
/**
31+
* Configures the ordering for Spring Security's Filter.
32+
*
33+
* @author Rob Winch
34+
* @since 1.3
35+
*/
36+
@Configuration
37+
@ConditionalOnWebApplication
38+
@EnableConfigurationProperties
39+
@AutoConfigureAfter(SpringBootWebSecurityConfiguration.class)
40+
public class SecurityFilterRegistrationAutoConfiguration {
41+
@Bean
42+
@ConditionalOnBean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
43+
public FilterRegistrationBean securityFilterChainRegistration(
44+
@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter,
45+
SecurityProperties securityProperties) {
46+
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
47+
registration.setOrder(securityProperties.getFilterOrder());
48+
registration
49+
.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
50+
return registration;
51+
}
52+
}

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java

-17
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,17 @@
2020
import java.util.Arrays;
2121
import java.util.List;
2222

23-
import javax.servlet.Filter;
2423
import javax.servlet.http.HttpServletRequest;
2524

2625
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.beans.factory.annotation.Qualifier;
2826
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
29-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3027
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3128
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3229
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3330
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
3431
import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers;
3532
import org.springframework.boot.autoconfigure.web.ErrorController;
3633
import org.springframework.boot.autoconfigure.web.ServerProperties;
37-
import org.springframework.boot.context.embedded.FilterRegistrationBean;
3834
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3935
import org.springframework.context.annotation.Bean;
4036
import org.springframework.context.annotation.Configuration;
@@ -50,7 +46,6 @@
5046
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
5147
import org.springframework.security.web.AuthenticationEntryPoint;
5248
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
53-
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
5449
import org.springframework.security.web.header.writers.HstsHeaderWriter;
5550
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
5651
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -98,18 +93,6 @@ public IgnoredPathsWebSecurityConfigurerAdapter ignoredPathsWebSecurityConfigure
9893
return new IgnoredPathsWebSecurityConfigurerAdapter();
9994
}
10095

101-
@Bean
102-
@ConditionalOnBean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
103-
public FilterRegistrationBean securityFilterChainRegistration(
104-
@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter,
105-
SecurityProperties securityProperties) {
106-
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
107-
registration.setOrder(securityProperties.getFilterOrder());
108-
registration
109-
.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
110-
return registration;
111-
}
112-
11396
public static void configureHeaders(HeadersConfigurer<?> configurer,
11497
SecurityProperties.Headers headers) throws Exception {
11598
if (headers.getHsts() != Headers.HSTS.NONE) {

spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
5656
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
5757
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
5858
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
59+
org.springframework.boot.autoconfigure.security.SecurityFilterRegistrationAutoConfiguration,\
5960
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
6061
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
6162
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SecurityAutoConfigurationTests.java

+64
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import org.junit.After;
2222
import org.junit.Test;
2323
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
25+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
26+
import org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector;
2427
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
2528
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
2629
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@@ -31,9 +34,13 @@
3134
import org.springframework.boot.test.EnvironmentTestUtils;
3235
import org.springframework.context.ApplicationEvent;
3336
import org.springframework.context.ApplicationListener;
37+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3438
import org.springframework.context.annotation.Bean;
3539
import org.springframework.context.annotation.Configuration;
3640
import org.springframework.core.annotation.Order;
41+
import org.springframework.core.io.DefaultResourceLoader;
42+
import org.springframework.core.type.StandardAnnotationMetadata;
43+
import org.springframework.mock.env.MockEnvironment;
3744
import org.springframework.mock.web.MockServletContext;
3845
import org.springframework.orm.jpa.JpaTransactionManager;
3946
import org.springframework.security.authentication.AuthenticationManager;
@@ -45,16 +52,19 @@
4552
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
4653
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
4754
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
55+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
4856
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
4957
import org.springframework.security.core.Authentication;
5058
import org.springframework.security.core.AuthenticationException;
5159
import org.springframework.security.core.authority.AuthorityUtils;
5260
import org.springframework.security.core.userdetails.UserDetailsService;
5361
import org.springframework.security.web.FilterChainProxy;
5462
import org.springframework.security.web.SecurityFilterChain;
63+
import org.springframework.util.ObjectUtils;
5564
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
5665

5766
import static org.junit.Assert.assertEquals;
67+
import static org.junit.Assert.assertFalse;
5868
import static org.junit.Assert.assertNotNull;
5969
import static org.junit.Assert.assertTrue;
6070
import static org.junit.Assert.fail;
@@ -90,11 +100,57 @@ public void testWebConfiguration() throws Exception {
90100
assertEquals(5, filterChains.size());
91101
}
92102

103+
// gh-3703
104+
@Test
105+
public void testDefaultFilterOrderWithSecurityAdapter() throws Exception {
106+
this.context = new AnnotationConfigWebApplicationContext();
107+
this.context.setServletContext(new MockServletContext());
108+
this.context.register(WebSecurity.class,
109+
SecurityAutoConfiguration.class,
110+
SecurityFilterRegistrationAutoConfiguration.class,
111+
ServerPropertiesAutoConfiguration.class,
112+
PropertyPlaceholderAutoConfiguration.class);
113+
this.context.refresh();
114+
assertEquals(
115+
0,
116+
this.context.getBean("securityFilterChainRegistration",
117+
FilterRegistrationBean.class).getOrder());
118+
}
119+
120+
@Test
121+
public void testSecurityFilterRegistrationAutoConfigurationRegisteredAutoConfiguration() throws Exception {
122+
EnableAutoConfigurationImportSelector selector = new EnableAutoConfigurationImportSelector();
123+
selector.setBeanFactory(new DefaultListableBeanFactory());
124+
selector.setEnvironment(new MockEnvironment());
125+
selector.setResourceLoader(new DefaultResourceLoader());
126+
String[] imports = selector.selectImports(new StandardAnnotationMetadata(AutoConfiguration.class));
127+
128+
assertTrue(ObjectUtils.containsElement(imports, "org.springframework.boot.autoconfigure.security.SecurityFilterRegistrationAutoConfiguration"));
129+
}
130+
131+
@Test
132+
public void testDefaultFilterOrderNotWeb() throws Exception {
133+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
134+
context.register(SecurityAutoConfiguration.class,
135+
SecurityFilterRegistrationAutoConfiguration.class,
136+
ServerPropertiesAutoConfiguration.class,
137+
PropertyPlaceholderAutoConfiguration.class);
138+
139+
try {
140+
context.refresh();
141+
assertFalse(
142+
context.containsBean("securityFilterChainRegistration"));
143+
} finally {
144+
context.close();
145+
}
146+
}
147+
93148
@Test
94149
public void testDefaultFilterOrder() throws Exception {
95150
this.context = new AnnotationConfigWebApplicationContext();
96151
this.context.setServletContext(new MockServletContext());
97152
this.context.register(SecurityAutoConfiguration.class,
153+
SecurityFilterRegistrationAutoConfiguration.class,
98154
ServerPropertiesAutoConfiguration.class,
99155
PropertyPlaceholderAutoConfiguration.class);
100156
this.context.refresh();
@@ -110,6 +166,7 @@ public void testCustomFilterOrder() throws Exception {
110166
EnvironmentTestUtils.addEnvironment(this.context, "security.filter-order:12345");
111167
this.context.setServletContext(new MockServletContext());
112168
this.context.register(SecurityAutoConfiguration.class,
169+
SecurityFilterRegistrationAutoConfiguration.class,
113170
ServerPropertiesAutoConfiguration.class,
114171
PropertyPlaceholderAutoConfiguration.class);
115172
this.context.refresh();
@@ -411,4 +468,11 @@ public UserDetailsService getUserDetails() {
411468

412469
}
413470

471+
@Configuration
472+
@EnableWebSecurity
473+
static class WebSecurity extends WebSecurityConfigurerAdapter {}
474+
475+
@Configuration
476+
@EnableAutoConfiguration
477+
static class AutoConfiguration {}
414478
}

0 commit comments

Comments
 (0)