mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-22 03:52:15 +00:00
SEC-2461: Multi WebSecurityConfiguration does not create null springSecurityFilterChain
This commit is contained in:
parent
ec8b48150d
commit
6b42a2eae1
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2013 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.security.config.annotation.web.configuration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
|
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class used to get all the {@link WebSecurityConfigurer} instances from the
|
||||||
|
* current {@link ApplicationContext} but ignoring the parent.
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
final class AutowiredWebSecurityConfigurersIgnoreParents {
|
||||||
|
|
||||||
|
private final ConfigurableListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
public AutowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
Assert.notNull(beanFactory,"beanFactory cannot be null");
|
||||||
|
this.beanFactory = beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
|
||||||
|
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
|
||||||
|
Map<String, WebSecurityConfigurer> beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class);
|
||||||
|
for(Entry<String,WebSecurityConfigurer> entry : beansOfType.entrySet()) {
|
||||||
|
webSecurityConfigurers.add(entry.getValue());
|
||||||
|
}
|
||||||
|
return webSecurityConfigurers;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,8 @@ import javax.servlet.Filter;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
@ -34,7 +36,6 @@ import org.springframework.core.annotation.AnnotationUtils;
|
|||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||||
import org.springframework.security.config.annotation.AlreadyBuiltException;
|
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||||
@ -88,11 +89,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
|||||||
if(!hasConfigurers) {
|
if(!hasConfigurers) {
|
||||||
throw new IllegalStateException("At least one non-null instance of "+ WebSecurityConfigurer.class.getSimpleName()+" must be exposed as a @Bean when using @EnableWebSecurity. Hint try extending "+ WebSecurityConfigurerAdapter.class.getSimpleName());
|
throw new IllegalStateException("At least one non-null instance of "+ WebSecurityConfigurer.class.getSimpleName()+" must be exposed as a @Bean when using @EnableWebSecurity. Hint try extending "+ WebSecurityConfigurerAdapter.class.getSimpleName());
|
||||||
}
|
}
|
||||||
try {
|
return webSecurity.build();
|
||||||
return webSecurity.build();
|
|
||||||
} catch (AlreadyBuiltException e) {
|
|
||||||
return webSecurity.getObject();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,7 +112,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
|||||||
*/
|
*/
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
|
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
|
||||||
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
|
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
|
||||||
webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
|
webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
|
||||||
if(debugEnabled != null) {
|
if(debugEnabled != null) {
|
||||||
webSecurity.debug(debugEnabled);
|
webSecurity.debug(debugEnabled);
|
||||||
@ -137,6 +134,10 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
|||||||
this.webSecurityConfigurers = webSecurityConfigurers;
|
this.webSecurityConfigurers = webSecurityConfigurers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom verision of the Spring provided AnnotationAwareOrderComparator
|
* A custom verision of the Spring provided AnnotationAwareOrderComparator
|
||||||
|
@ -17,31 +17,28 @@ package org.springframework.security.config.annotation.web.configuration;
|
|||||||
|
|
||||||
import static org.junit.Assert.*
|
import static org.junit.Assert.*
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException
|
import org.springframework.beans.factory.BeanCreationException
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.core.annotation.Order
|
import org.springframework.core.annotation.Order
|
||||||
import org.springframework.expression.ExpressionParser;
|
import org.springframework.expression.ExpressionParser
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest
|
||||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
import org.springframework.security.access.expression.SecurityExpressionHandler
|
||||||
import org.springframework.security.authentication.AuthenticationManager
|
import org.springframework.security.authentication.AuthenticationManager
|
||||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
|
||||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.builders.WebSecurity
|
import org.springframework.security.config.annotation.web.builders.WebSecurity
|
||||||
import org.springframework.security.web.FilterChainProxy
|
import org.springframework.security.web.FilterChainProxy
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator
|
||||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
|
||||||
import org.springframework.security.web.access.expression.WebSecurityExpressionHandler;
|
import org.springframework.security.web.access.expression.WebSecurityExpressionHandler
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -313,4 +310,36 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
|
||||||
|
setup:
|
||||||
|
def parent = loadConfig(ParentConfig)
|
||||||
|
def child = new AnnotationConfigApplicationContext()
|
||||||
|
child.register(ChildConfig)
|
||||||
|
child.parent = parent
|
||||||
|
when:
|
||||||
|
child.refresh()
|
||||||
|
then: "springSecurityFilterChain can be found in parent and child"
|
||||||
|
parent.getBean("springSecurityFilterChain")
|
||||||
|
child.getBean("springSecurityFilterChain")
|
||||||
|
and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
|
||||||
|
parent.containsBeanDefinition("springSecurityFilterChain")
|
||||||
|
child.containsBeanDefinition("springSecurityFilterChain")
|
||||||
|
cleanup:
|
||||||
|
child?.close()
|
||||||
|
// parent.close() is in superclass
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration
|
||||||
|
static class ParentConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
@Autowired
|
||||||
|
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||||
|
auth.inMemoryAuthentication()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration
|
||||||
|
static class ChildConfig extends WebSecurityConfigurerAdapter { }
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,10 @@ package org.springframework.security.config.annotation.web.configuration.sec2377
|
|||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
public class Sec2377BConfig {
|
public class Sec2377BConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user