From b443baef04dbca1e48bd69b77944af86771a7dca Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 22 Sep 2016 15:13:05 -0500 Subject: [PATCH] Polish GrantedAuthorityDefaults * Move GrantedAuthorityDefaults to config module * Move setting of default role into config module vs ApplicationContextAware Issue gh-3701 --- .../LdapAuthenticationProviderConfigurer.java | 12 +- .../GlobalMethodSecurityConfiguration.java | 11 +- .../ExpressionUrlAuthorizationConfigurer.java | 6 + .../web/configurers/ServletApiConfigurer.java | 12 +- .../core}/GrantedAuthorityDefaults.java | 20 +- ...nvocationSecurityMetadataSourceParser.java | 18 +- .../GrantedAuthorityDefaultsParserUtils.java | 61 ++++++ .../config/http/HttpConfigurationBuilder.java | 48 ++++- ...balMethodSecurityBeanDefinitionParser.java | 54 +++++- ...balMethodSecurityConfigurationTests.groovy | 2 +- .../NamespaceGlobalMethodSecurityTests.groovy | 43 +--- .../core/GrantedAuthorityDefaultsJcTests.java | 183 ++++++++++++++++++ .../GrantedAuthorityDefaultsXmlTests.java | 146 ++++++++++++++ .../config/core/HelloWorldMessageService.java | 36 ++++ .../security/config/core/MessageService.java | 24 +++ ...antedAuthorityDefaultsXmlTests-context.xml | 29 +++ .../DefaultLdapAuthoritiesPopulator.java | 84 ++++---- .../userdetails/LdapUserDetailsMapper.java | 39 ++-- .../DefaultLdapAuthoritiesPopulatorTests.java | 60 ------ .../LdapUserDetailsMapperTests.java | 32 --- .../DefaultWebSecurityExpressionHandler.java | 21 +- ...curityContextHolderAwareRequestFilter.java | 22 +-- ...aultWebSecurityExpressionHandlerTests.java | 27 +-- ...yContextHolderAwareRequestFilterTests.java | 31 --- 24 files changed, 685 insertions(+), 336 deletions(-) rename {core/src/main/java/org/springframework/security/config => config/src/main/java/org/springframework/security/config/core}/GrantedAuthorityDefaults.java (68%) create mode 100644 config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java create mode 100644 config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java create mode 100644 config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java create mode 100755 config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java create mode 100755 config/src/test/java/org/springframework/security/config/core/MessageService.java create mode 100755 config/src/test/resources/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests-context.xml delete mode 100644 ldap/src/test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index f50aca3aae..ba4780c9f4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -23,11 +23,11 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder; import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer; +import org.springframework.security.config.core.GrantedAuthorityDefaults; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.ldap.DefaultSpringSecurityContextSource; @@ -61,7 +61,7 @@ public class LdapAuthenticationProviderConfigurer rolePrefix(String rolePrefix) { - this.rolePrefix = new GrantedAuthorityDefaults(rolePrefix); + this.rolePrefix = rolePrefix; return this; } @@ -616,4 +616,4 @@ public class LdapAuthenticationProviderConfigurer> extend if (trustResolver != null) { securityContextRequestFilter.setTrustResolver(trustResolver); } + ApplicationContext context = http.getSharedObject(ApplicationContext.class); + if(context != null) { + String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); + if(grantedAuthorityDefaultsBeanNames.length == 1) { + GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + securityContextRequestFilter.setRolePrefix(grantedAuthorityDefaults.getRolePrefix()); + } + } securityContextRequestFilter = postProcess(securityContextRequestFilter); http.addFilter(securityContextRequestFilter); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/springframework/security/config/GrantedAuthorityDefaults.java b/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java similarity index 68% rename from core/src/main/java/org/springframework/security/config/GrantedAuthorityDefaults.java rename to config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java index d8c990317d..0168fe0d47 100644 --- a/core/src/main/java/org/springframework/security/config/GrantedAuthorityDefaults.java +++ b/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java @@ -13,26 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.security.config; +package org.springframework.security.config.core; + +import org.springframework.security.core.GrantedAuthority; /** + * Allows providing defaults for {@link GrantedAuthority} + * * @author Eddú Meléndez * @since 4.2.0 */ -public class GrantedAuthorityDefaults { +public final class GrantedAuthorityDefaults { - private String rolePrefix = "ROLE_"; + private final String rolePrefix; public GrantedAuthorityDefaults(String rolePrefix) { this.rolePrefix = rolePrefix; } + /** + * The default prefix used with role based authorization. Default is "ROLE_". + * + * @return the default role prefix + */ public String getRolePrefix() { return this.rolePrefix; } - - public void setRolePrefix(String rolePrefix) { - this.rolePrefix = rolePrefix; - } - } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java index d5669d52be..955a4d6b6f 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java @@ -15,8 +15,12 @@ */ package org.springframework.security.config.http; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -33,9 +37,6 @@ import org.springframework.security.web.access.intercept.DefaultFilterInvocation import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; - -import java.util.List; /** * Allows for convenient creation of a {@link FilterInvocationSecurityMetadataSource} bean @@ -133,8 +134,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit } static String registerDefaultExpressionHandler(ParserContext pc) { - BeanDefinition expressionHandler = BeanDefinitionBuilder.rootBeanDefinition( - DefaultWebSecurityExpressionHandler.class).getBeanDefinition(); + BeanDefinition expressionHandler = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, DefaultWebSecurityExpressionHandlerBeanFactory.class); String expressionHandlerRef = pc.getReaderContext().generateBeanName( expressionHandler); pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, @@ -223,4 +223,12 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit return filterInvocationDefinitionMap; } + static class DefaultWebSecurityExpressionHandlerBeanFactory extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + private DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); + + public DefaultWebSecurityExpressionHandler getBean() { + handler.setDefaultRolePrefix(this.rolePrefix); + return handler; + } + } } diff --git a/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java b/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java new file mode 100644 index 0000000000..160520aa41 --- /dev/null +++ b/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2016 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.http; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.security.config.core.GrantedAuthorityDefaults; + +/** + * @author Rob Winch + * @since 4.2 + */ +class GrantedAuthorityDefaultsParserUtils { + + + static RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, Class beanFactoryClass) { + RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass); + String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition); + pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition); + + RootBeanDefinition bean = new RootBeanDefinition(); + bean.setFactoryBeanName(beanFactoryRef); + bean.setFactoryMethodName("getBean"); + return bean; + } + + static abstract class AbstractGrantedAuthorityDefaultsBeanFactory implements ApplicationContextAware { + protected String rolePrefix = "ROLE_"; + + @Override + public final void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + String[] grantedAuthorityDefaultsBeanNames = applicationContext.getBeanNamesForType(GrantedAuthorityDefaults.class); + if(grantedAuthorityDefaultsBeanNames.length == 1) { + GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + this.rolePrefix = grantedAuthorityDefaults.getRolePrefix(); + } + } + + abstract Object getBean(); + } + + private GrantedAuthorityDefaultsParserUtils() {} +} diff --git a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java index f8534a62d5..acc9ff7129 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java @@ -18,9 +18,12 @@ package org.springframework.security.config.http; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; + import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; +import org.w3c.dom.Element; + import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanReference; @@ -37,6 +40,7 @@ import org.springframework.security.access.vote.AffirmativeBased; import org.springframework.security.access.vote.AuthenticatedVoter; import org.springframework.security.access.vote.RoleVoter; import org.springframework.security.config.Elements; +import org.springframework.security.config.http.GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl; @@ -65,17 +69,30 @@ import org.springframework.security.web.savedrequest.RequestCacheAwareFilter; import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter; import org.springframework.security.web.session.ConcurrentSessionFilter; import org.springframework.security.web.session.SessionManagementFilter; -import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy; import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy; +import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; -import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.*; -import static org.springframework.security.config.http.SecurityFilters.*; +import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_FILTERS; +import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_HTTP_METHOD; +import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN; +import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL; +import static org.springframework.security.config.http.SecurityFilters.CHANNEL_FILTER; +import static org.springframework.security.config.http.SecurityFilters.CONCURRENT_SESSION_FILTER; +import static org.springframework.security.config.http.SecurityFilters.CORS_FILTER; +import static org.springframework.security.config.http.SecurityFilters.CSRF_FILTER; +import static org.springframework.security.config.http.SecurityFilters.FILTER_SECURITY_INTERCEPTOR; +import static org.springframework.security.config.http.SecurityFilters.HEADERS_FILTER; +import static org.springframework.security.config.http.SecurityFilters.JAAS_API_SUPPORT_FILTER; +import static org.springframework.security.config.http.SecurityFilters.REQUEST_CACHE_FILTER; +import static org.springframework.security.config.http.SecurityFilters.SECURITY_CONTEXT_FILTER; +import static org.springframework.security.config.http.SecurityFilters.SERVLET_API_SUPPORT_FILTER; +import static org.springframework.security.config.http.SecurityFilters.SESSION_MANAGEMENT_FILTER; +import static org.springframework.security.config.http.SecurityFilters.WEB_ASYNC_MANAGER_FILTER; /** * Stateful class which helps HttpSecurityBDP to create the configuration for the @@ -543,8 +560,7 @@ class HttpConfigurationBuilder { } if ("true".equals(provideServletApi)) { - servApiFilter = new RootBeanDefinition( - SecurityContextHolderAwareRequestFilter.class); + servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, SecurityContextHolderAwareRequestFilterBeanFactory.class); servApiFilter.getPropertyValues().add("authenticationManager", authenticationManager); } @@ -715,7 +731,7 @@ class HttpConfigurationBuilder { voters.add(expressionVoter.getBeanDefinition()); } else { - voters.add(new RootBeanDefinition(RoleVoter.class)); + voters.add(GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, RoleVoterBeanFactory.class)); voters.add(new RootBeanDefinition(AuthenticatedVoter.class)); } accessDecisionMgr = new RootBeanDefinition(AffirmativeBased.class); @@ -852,4 +868,22 @@ class HttpConfigurationBuilder { return filters; } + + static class RoleVoterBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private RoleVoter voter = new RoleVoter(); + + public RoleVoter getBean() { + voter.setRolePrefix(this.rolePrefix); + return voter; + } + } + + static class SecurityContextHolderAwareRequestFilterBeanFactory extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + private SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter(); + + public SecurityContextHolderAwareRequestFilter getBean() { + filter.setRolePrefix(this.rolePrefix); + return filter; + } + } } diff --git a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java index c22b1ef2ea..ca6f5c838e 100644 --- a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java @@ -45,6 +45,8 @@ import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; @@ -71,6 +73,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.BeanIds; import org.springframework.security.config.Elements; import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean; +import org.springframework.security.config.core.GrantedAuthorityDefaults; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.util.Assert; @@ -198,8 +201,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP expressionHandlerRef)); } else { - BeanDefinition expressionHandler = new RootBeanDefinition( - DefaultMethodSecurityExpressionHandler.class); + RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc, DefaultMethodSecurityExpressionHandlerBeanFactory.class); + expressionHandlerRef = pc.getReaderContext().generateBeanName( expressionHandler); pc.registerBeanComponent(new BeanComponentDefinition( @@ -240,8 +243,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } if (jsr250Enabled) { - delegates.add(BeanDefinitionBuilder.rootBeanDefinition( - Jsr250MethodSecurityMetadataSource.class).getBeanDefinition()); + RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc, Jsr250MethodSecurityMetadataSourceBeanFactory.class); + delegates.add(jsrMetadataSource); } // Now create a Map for each @@ -474,6 +477,17 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor); } + private RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, Class beanFactoryClass) { + RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass); + String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition); + pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition); + + RootBeanDefinition bean = new RootBeanDefinition(); + bean.setFactoryBeanName(beanFactoryRef); + bean.setFactoryMethodName("getBean"); + return bean; + } + /** * Delays the lookup of the AuthenticationManager within MethodSecurityInterceptor, to * prevent issues like SEC-933. @@ -522,6 +536,38 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } } + static class Jsr250MethodSecurityMetadataSourceBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private Jsr250MethodSecurityMetadataSource source = new Jsr250MethodSecurityMetadataSource(); + + public Jsr250MethodSecurityMetadataSource getBean() { + source.setDefaultRolePrefix(this.rolePrefix); + return source; + } + } + + static class DefaultMethodSecurityExpressionHandlerBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); + + public DefaultMethodSecurityExpressionHandler getBean() { + handler.setDefaultRolePrefix(this.rolePrefix); + return handler; + } + } + + static abstract class AbstractGrantedAuthorityDefaultsBeanFactory implements ApplicationContextAware { + protected String rolePrefix = "ROLE_"; + + @Override + public final void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + String[] grantedAuthorityDefaultsBeanNames = applicationContext.getBeanNamesForType(GrantedAuthorityDefaults.class); + if(grantedAuthorityDefaultsBeanNames.length == 1) { + GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + this.rolePrefix = grantedAuthorityDefaults.getRolePrefix(); + } + } + } + /** * Delays setting a bean of a given name to be lazyily initialized until after all the * beans are registered. diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy index e045ff3779..109688f0d0 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.method.configuration import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl -import org.springframework.security.config.GrantedAuthorityDefaults; import java.lang.reflect.Proxy; @@ -28,6 +27,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter import org.springframework.security.config.annotation.method.configuration.NamespaceGlobalMethodSecurityTests.BaseMethodConfig; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter +import org.springframework.security.config.core.GrantedAuthorityDefaults; import javax.sql.DataSource diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy index f709c5fe73..1eec425878 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy @@ -17,7 +17,6 @@ package org.springframework.security.config.annotation.method.configuration import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor -import org.springframework.security.config.GrantedAuthorityDefaults import static org.assertj.core.api.Assertions.assertThat import static org.junit.Assert.fail @@ -50,7 +49,7 @@ import org.springframework.security.authentication.TestingAuthenticationToken import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.authentication.BaseAuthenticationConfig; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; +import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration import org.springframework.security.core.Authentication import org.springframework.security.core.context.SecurityContextHolder @@ -148,39 +147,6 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec { public static class Jsr250Config extends BaseMethodConfig { } - def "enable jsr250 with custom role prefix"() { - when: - context = new AnnotationConfigApplicationContext(Jsr250WithCustomRolePrefixConfig) - MethodSecurityService service = context.getBean(MethodSecurityService) - then: "@Secured and @PreAuthorize are ignored" - service.secured() == null - service.preAuthorize() == null - - when: "@DenyAll method invoked" - service.jsr250() - then: "access is denied" - thrown(AccessDeniedException) - when: "@PermitAll method invoked" - String jsr250PermitAll = service.jsr250PermitAll() - then: "access is allowed" - jsr250PermitAll == null - when: - Jsr250MethodSecurityMetadataSource jsr250MethodSecurity = context.getBean(Jsr250MethodSecurityMetadataSource) - then: - jsr250MethodSecurity.defaultRolePrefix == "ROLE:" - } - - @EnableGlobalMethodSecurity(jsr250Enabled = true) - @Configuration - public static class Jsr250WithCustomRolePrefixConfig extends BaseMethodConfig { - - @Bean - public GrantedAuthorityDefaults ga() { - return new GrantedAuthorityDefaults("ROLE:") - } - - } - // --- metadata-source-ref --- def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() { @@ -355,7 +321,7 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec { context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig) MethodSecurityService service = context.getBean(MethodSecurityService) then: - service.runAs().authorities.find { it.authority == "ROLE:RUN_AS_SUPER"} + service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"} } @EnableGlobalMethodSecurity(securedEnabled = true) @@ -366,11 +332,6 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec { runAsManager.setKey("some key") return runAsManager } - - @Bean - public GrantedAuthorityDefaults ga() { - return new GrantedAuthorityDefaults("ROLE:") - } } // --- secured-annotation --- diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java new file mode 100644 index 0000000000..f35139dd99 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java @@ -0,0 +1,183 @@ +/* + * Copyright 2002-2016 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.core; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class GrantedAuthorityDefaultsJcTests { + @Autowired + FilterChainProxy springSecurityFilterChain; + @Autowired + MessageService messageService; + + MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; + + @Before + public void setup() { + setup("USER"); + + request = new MockHttpServletRequest(); + request.setMethod("GET"); + response = new MockHttpServletResponse(); + chain = new MockFilterChain(); + } + + @After + public void cleanup() { + SecurityContextHolder.clearContext(); + } + + @Test + public void doFilter() throws Exception { + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); + } + + @Test + public void doFilterDenied() throws Exception { + setup("DENIED"); + + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); + } + + @Test + public void message() { + messageService.getMessage(); + } + + @Test + public void jsrMessage() { + messageService.getJsrMessage(); + } + + @Test(expected = AccessDeniedException.class) + public void messageDenied() { + setup("DENIED"); + + messageService.getMessage(); + } + + @Test(expected = AccessDeniedException.class) + public void jsrMessageDenied() { + setup("DENIED"); + + messageService.getJsrMessage(); + } + + // SEC-2926 + @Test + public void doFilterIsUserInRole() throws Exception { + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + chain = new MockFilterChain() { + + @Override + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + assertThat(httpRequest.isUserInRole("USER")).isTrue(); + assertThat(httpRequest.isUserInRole("INVALID")).isFalse(); + super.doFilter(request, response); + } + + }; + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(chain.getRequest()).isNotNull(); + } + + private void setup(String role) { + TestingAuthenticationToken user = new TestingAuthenticationToken("user", "password", role); + SecurityContextHolder.getContext().setAuthentication(user); + } + + @Configuration + @EnableWebSecurity + @EnableGlobalMethodSecurity(prePostEnabled=true, jsr250Enabled=true) + static class Config extends WebSecurityConfigurerAdapter { + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest().access("hasRole('USER')"); + } + + @Bean + public MessageService messageService() { + return new HelloWorldMessageService(); + } + + @Bean + public static GrantedAuthorityDefaults grantedAuthorityDefaults() { + return new GrantedAuthorityDefaults(""); + } + } +} diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java new file mode 100644 index 0000000000..c36341ab50 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java @@ -0,0 +1,146 @@ +/* + * Copyright 2002-2016 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.core; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class GrantedAuthorityDefaultsXmlTests { + @Autowired + FilterChainProxy springSecurityFilterChain; + @Autowired + MessageService messageService; + + MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; + + @Before + public void setup() { + setup("USER"); + + request = new MockHttpServletRequest(); + request.setMethod("GET"); + response = new MockHttpServletResponse(); + chain = new MockFilterChain(); + } + + @After + public void cleanup() { + SecurityContextHolder.clearContext(); + } + + @Test + public void doFilter() throws Exception { + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); + } + + @Test + public void doFilterDenied() throws Exception { + setup("DENIED"); + + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); + } + + @Test + public void message() { + messageService.getMessage(); + } + + @Test + public void jsrMessage() { + messageService.getJsrMessage(); + } + + @Test(expected = AccessDeniedException.class) + public void messageDenied() { + setup("DENIED"); + + messageService.getMessage(); + } + + @Test(expected = AccessDeniedException.class) + public void jsrMessageDenied() { + setup("DENIED"); + + messageService.getJsrMessage(); + } + + // SEC-2926 + @Test + public void doFilterIsUserInRole() throws Exception { + SecurityContext context = SecurityContextHolder.getContext(); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + chain = new MockFilterChain() { + + @Override + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + assertThat(httpRequest.isUserInRole("USER")).isTrue(); + assertThat(httpRequest.isUserInRole("INVALID")).isFalse(); + super.doFilter(request, response); + } + + }; + + springSecurityFilterChain.doFilter(request, response, chain); + + assertThat(chain.getRequest()).isNotNull(); + } + + private void setup(String role) { + TestingAuthenticationToken user = new TestingAuthenticationToken("user", "password", role); + SecurityContextHolder.getContext().setAuthentication(user); + } +} diff --git a/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java b/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java new file mode 100755 index 0000000000..714680aec9 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2016 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.core; + +import javax.annotation.security.RolesAllowed; + +import org.springframework.security.access.prepost.PreAuthorize; + +/** + * @author Rob Winch + */ +public class HelloWorldMessageService implements MessageService { + + @PreAuthorize("hasRole('USER')") + public String getMessage() { + return "Hello World"; + } + + @RolesAllowed("USER") + public String getJsrMessage() { + return "Hello JSR"; + } +} diff --git a/config/src/test/java/org/springframework/security/config/core/MessageService.java b/config/src/test/java/org/springframework/security/config/core/MessageService.java new file mode 100755 index 0000000000..f7e34a6271 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/core/MessageService.java @@ -0,0 +1,24 @@ +/* + * Copyright 2002-2016 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.core; + +/** + * @author Rob Winch + */ +public interface MessageService { + String getMessage(); + String getJsrMessage(); +} diff --git a/config/src/test/resources/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests-context.xml b/config/src/test/resources/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests-context.xml new file mode 100755 index 0000000000..82f3a4ad55 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests-context.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java index 82ef6202c6..1acdedc826 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java @@ -16,29 +16,25 @@ package org.springframework.security.ldap.userdetails; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.security.config.GrantedAuthorityDefaults; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.ldap.SpringSecurityLdapTemplate; -import org.springframework.ldap.core.ContextSource; -import org.springframework.ldap.core.DirContextOperations; -import org.springframework.ldap.core.LdapTemplate; -import org.springframework.util.Assert; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.naming.directory.SearchControls; - import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.naming.directory.SearchControls; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.ldap.SpringSecurityLdapTemplate; +import org.springframework.util.Assert; + /** * The default strategy for obtaining user role information from the directory. *

@@ -101,7 +97,7 @@ import java.util.Set; * @author Luke Taylor * @author Filip Hanik */ -public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator, ApplicationContextAware { +public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { // ~ Static fields/initializers // ===================================================================================== @@ -144,7 +140,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator /** * The role prefix that will be prepended to each role name */ - private GrantedAuthorityDefaults rolePrefix = new GrantedAuthorityDefaults("ROLE_"); + private String rolePrefix = "ROLE_"; /** * Should we convert the role name to uppercase */ @@ -164,7 +160,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) { Assert.notNull(contextSource, "contextSource must not be null"); - ldapTemplate = new SpringSecurityLdapTemplate(contextSource); + this.ldapTemplate = new SpringSecurityLdapTemplate(contextSource); getLdapTemplate().setSearchControls(getSearchControls()); this.groupSearchBase = groupSearchBase; @@ -172,7 +168,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator logger.info("groupSearchBase is null. No group search will be performed."); } else if (groupSearchBase.length() == 0) { - logger.info("groupSearchBase is empty. Searches will be performed from the context source base"); + logger.info( + "groupSearchBase is empty. Searches will be performed from the context source base"); } } @@ -201,6 +198,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @param user the user who's authorities are required * @return the set of roles granted to the user. */ + @Override public final Collection getGrantedAuthorities( DirContextOperations user, String username) { String userDn = user.getNameInNamespace(); @@ -217,8 +215,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator roles.addAll(extraRoles); } - if (defaultRole != null) { - roles.add(defaultRole); + if (this.defaultRole != null) { + roles.add(this.defaultRole); } List result = new ArrayList(roles.size()); @@ -236,13 +234,13 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator if (logger.isDebugEnabled()) { logger.debug("Searching for roles for user '" + username + "', DN = " + "'" - + userDn + "', with filter " + groupSearchFilter + + userDn + "', with filter " + this.groupSearchFilter + " in search base '" + getGroupSearchBase() + "'"); } Set userRoles = getLdapTemplate().searchForSingleAttributeValues( - getGroupSearchBase(), groupSearchFilter, - new String[] { userDn, username }, groupRoleAttribute); + getGroupSearchBase(), this.groupSearchFilter, + new String[] { userDn, username }, this.groupRoleAttribute); if (logger.isDebugEnabled()) { logger.debug("Roles from search: " + userRoles); @@ -250,11 +248,11 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator for (String role : userRoles) { - if (convertToUpperCase) { + if (this.convertToUpperCase) { role = role.toUpperCase(); } - authorities.add(new SimpleGrantedAuthority(rolePrefix.getRolePrefix() + role)); + authorities.add(new SimpleGrantedAuthority(this.rolePrefix + role)); } return authorities; @@ -265,7 +263,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator } protected String getGroupSearchBase() { - return groupSearchBase; + return this.groupSearchBase; } /** @@ -301,7 +299,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator */ public void setRolePrefix(String rolePrefix) { Assert.notNull(rolePrefix, "rolePrefix must not be null"); - this.rolePrefix = new GrantedAuthorityDefaults(rolePrefix); + this.rolePrefix = rolePrefix; } /** @@ -314,7 +312,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator public void setSearchSubtree(boolean searchSubtree) { int searchScope = searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE; - searchControls.setSearchScope(searchScope); + this.searchControls.setSearchScope(searchScope); } /** @@ -334,7 +332,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see org.springframework.security.ldap.SpringSecurityLdapTemplate */ protected SpringSecurityLdapTemplate getLdapTemplate() { - return ldapTemplate; + return this.ldapTemplate; } /** @@ -344,7 +342,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see #setGroupRoleAttribute(String) */ protected final String getGroupRoleAttribute() { - return groupRoleAttribute; + return this.groupRoleAttribute; } /** @@ -354,7 +352,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see #setGroupSearchFilter(String) */ protected final String getGroupSearchFilter() { - return groupSearchFilter; + return this.groupSearchFilter; } /** @@ -364,7 +362,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see #setRolePrefix(String) */ protected final String getRolePrefix() { - return this.rolePrefix.getRolePrefix(); + return this.rolePrefix; } /** @@ -374,7 +372,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see #setConvertToUpperCase(boolean) */ protected final boolean isConvertToUpperCase() { - return convertToUpperCase; + return this.convertToUpperCase; } /** @@ -384,7 +382,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @see #setDefaultRole(String) */ private GrantedAuthority getDefaultRole() { - return defaultRole; + return this.defaultRole; } /** @@ -393,16 +391,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * @return the search controls */ private SearchControls getSearchControls() { - return searchControls; + return this.searchControls; } - - @Override - public void setApplicationContext(ApplicationContext context) throws - BeansException { - String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); - if (beanNames.length == 1) { - this.rolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class); - } - } - } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java index 250a072b96..e07621e83b 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java @@ -21,12 +21,8 @@ import java.util.Collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -41,29 +37,30 @@ import org.springframework.util.Assert; * @author Luke Taylor * @author Eddú Meléndez */ -public class LdapUserDetailsMapper implements UserDetailsContextMapper, ApplicationContextAware { +public class LdapUserDetailsMapper implements UserDetailsContextMapper { // ~ Instance fields // ================================================================================================ private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class); private String passwordAttributeName = "userPassword"; - private GrantedAuthorityDefaults rolePrefix = new GrantedAuthorityDefaults("ROLE_"); + private String rolePrefix = "ROLE_"; private String[] roleAttributes = null; private boolean convertToUpperCase = true; // ~ Methods // ======================================================================================================== + @Override public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection authorities) { String dn = ctx.getNameInNamespace(); - logger.debug("Mapping user details from context with DN: " + dn); + this.logger.debug("Mapping user details from context with DN: " + dn); LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence(); essence.setDn(dn); - Object passwordValue = ctx.getObjectAttribute(passwordAttributeName); + Object passwordValue = ctx.getObjectAttribute(this.passwordAttributeName); if (passwordValue != null) { essence.setPassword(mapPassword(passwordValue)); @@ -72,12 +69,13 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper, Applicat essence.setUsername(username); // Map the roles - for (int i = 0; (roleAttributes != null) && (i < roleAttributes.length); i++) { - String[] rolesForAttribute = ctx.getStringAttributes(roleAttributes[i]); + for (int i = 0; (this.roleAttributes != null) + && (i < this.roleAttributes.length); i++) { + String[] rolesForAttribute = ctx.getStringAttributes(this.roleAttributes[i]); if (rolesForAttribute == null) { - logger.debug("Couldn't read role attribute '" + roleAttributes[i] - + "' for user " + dn); + this.logger.debug("Couldn't read role attribute '" + + this.roleAttributes[i] + "' for user " + dn); continue; } @@ -110,6 +108,7 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper, Applicat } + @Override public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { throw new UnsupportedOperationException( "LdapUserDetailsMapper only supports reading from a context. Please" @@ -149,10 +148,10 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper, Applicat */ protected GrantedAuthority createAuthority(Object role) { if (role instanceof String) { - if (convertToUpperCase) { + if (this.convertToUpperCase) { role = ((String) role).toUpperCase(); } - return new SimpleGrantedAuthority(this.rolePrefix.getRolePrefix() + role); + return new SimpleGrantedAuthority(this.rolePrefix + role); } return null; } @@ -194,16 +193,6 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper, Applicat * @param rolePrefix the prefix (defaults to "ROLE_"). */ public void setRolePrefix(String rolePrefix) { - this.rolePrefix = new GrantedAuthorityDefaults(rolePrefix); + this.rolePrefix = rolePrefix; } - - @Override - public void setApplicationContext(ApplicationContext context) throws - BeansException { - String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); - if (beanNames.length == 1) { - this.rolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class); - } - } - } diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java deleted file mode 100644 index 4f9f9e9c7c..0000000000 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2002-2016 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.ldap.userdetails; - -import org.junit.Test; - -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.ldap.core.ContextSource; -import org.springframework.security.config.GrantedAuthorityDefaults; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * @author Eddú Meléndez - */ -public class DefaultLdapAuthoritiesPopulatorTests { - - @Test - public void testDefaultRolePrefix() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(LdapAuthoritiesPopulatorConfiguration.class); - context.refresh(); - - DefaultLdapAuthoritiesPopulator ldapPopulator = context.getBean(DefaultLdapAuthoritiesPopulator.class); - assertThat(ldapPopulator.getRolePrefix()).isEqualTo("ROL_"); - } - - @Configuration - static class LdapAuthoritiesPopulatorConfiguration { - - @Bean - public GrantedAuthorityDefaults authorityDefaults() { - return new GrantedAuthorityDefaults("ROL_"); - } - - @Bean - public DefaultLdapAuthoritiesPopulator ldapAuthoritiesPopulator() { - ContextSource contextSource = mock(ContextSource.class); - return new DefaultLdapAuthoritiesPopulator(contextSource, "ou=groups"); - } - - } - -} diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java index 7da6005ff5..294a23a913 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java @@ -21,14 +21,9 @@ import javax.naming.directory.BasicAttributes; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -100,31 +95,4 @@ public class LdapUserDetailsMapperTests { assertThat(user.getPassword()).isEqualTo("mypassword"); } - @Test - public void testDefaultRolePrefix() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(LdapUserDetailsMapperConfiguration.class); - context.refresh(); - - LdapUserDetailsMapper ldapUserDetailsMapper = context.getBean(LdapUserDetailsMapper.class); - - GrantedAuthorityDefaults rolePrefix = (GrantedAuthorityDefaults) ReflectionTestUtils.getField(ldapUserDetailsMapper, "rolePrefix"); - assertThat(rolePrefix.getRolePrefix()).isEqualTo("ROL_"); - } - - @Configuration - static class LdapUserDetailsMapperConfiguration { - - @Bean - public GrantedAuthorityDefaults authorityDefaults() { - return new GrantedAuthorityDefaults("ROL_"); - } - - @Bean - public LdapUserDetailsMapper ldapUserDetailsMapper() { - return new LdapUserDetailsMapper(); - } - - } - } diff --git a/web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java b/web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java index 7cbeec399b..df2e573130 100644 --- a/web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java +++ b/web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java @@ -15,14 +15,11 @@ */ package org.springframework.security.web.access.expression; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; import org.springframework.security.access.expression.AbstractSecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionOperations; import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.authentication.AuthenticationTrustResolverImpl; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.Authentication; import org.springframework.security.web.FilterInvocation; import org.springframework.util.Assert; @@ -38,7 +35,7 @@ public class DefaultWebSecurityExpressionHandler extends SecurityExpressionHandler { private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); - private GrantedAuthorityDefaults defaultRolePrefix = new GrantedAuthorityDefaults("ROLE_"); + private String defaultRolePrefix = "ROLE_"; @Override protected SecurityExpressionOperations createSecurityExpressionRoot( @@ -47,7 +44,7 @@ public class DefaultWebSecurityExpressionHandler extends root.setPermissionEvaluator(getPermissionEvaluator()); root.setTrustResolver(trustResolver); root.setRoleHierarchy(getRoleHierarchy()); - root.setDefaultRolePrefix(this.defaultRolePrefix.getRolePrefix()); + root.setDefaultRolePrefix(this.defaultRolePrefix); return root; } @@ -78,16 +75,6 @@ public class DefaultWebSecurityExpressionHandler extends * @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_". */ public void setDefaultRolePrefix(String defaultRolePrefix) { - this.defaultRolePrefix = new GrantedAuthorityDefaults(defaultRolePrefix); + this.defaultRolePrefix = defaultRolePrefix; } - - @Override - public void setApplicationContext(ApplicationContext context) { - super.setApplicationContext(context); - String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); - if (beanNames.length == 1) { - this.defaultRolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class); - } - } - -} \ No newline at end of file +} diff --git a/web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java b/web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java index 0043c3f599..b6aa92c58e 100644 --- a/web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java +++ b/web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java @@ -27,13 +27,9 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.authentication.AuthenticationTrustResolverImpl; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; @@ -77,11 +73,11 @@ import org.springframework.web.filter.GenericFilterBean; * @author Rob Winch * @author Eddú Meléndez */ -public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean implements ApplicationContextAware { +public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean { // ~ Instance fields // ================================================================================================ - private GrantedAuthorityDefaults rolePrefix = new GrantedAuthorityDefaults("ROLE_"); + private String rolePrefix = "ROLE_"; private HttpServletRequestFactory requestFactory; @@ -98,7 +94,7 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean i public void setRolePrefix(String rolePrefix) { Assert.notNull(rolePrefix, "Role prefix must not be null"); - this.rolePrefix = new GrantedAuthorityDefaults(rolePrefix); + this.rolePrefix = rolePrefix; updateFactory(); } @@ -182,7 +178,7 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean i } private void updateFactory() { - String rolePrefix = this.rolePrefix.getRolePrefix(); + String rolePrefix = this.rolePrefix; this.requestFactory = isServlet3() ? createServlet3Factory(rolePrefix) : new HttpServlet25RequestFactory(this.trustResolver, rolePrefix); } @@ -216,14 +212,4 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean i private boolean isServlet3() { return ClassUtils.hasMethod(ServletRequest.class, "startAsync"); } - - @Override - public void setApplicationContext(ApplicationContext context) throws - BeansException { - String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); - if (beanNames.length == 1) { - this.rolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class); - } - } - } diff --git a/web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java b/web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java index f0f1f658c4..c77a059e1c 100644 --- a/web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java @@ -16,16 +16,13 @@ package org.springframework.security.web.access.expression; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; + import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.StaticApplicationContext; import org.springframework.expression.EvaluationContext; @@ -33,11 +30,14 @@ import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.AuthenticationTrustResolver; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.FilterInvocation; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + @RunWith(MockitoJUnitRunner.class) public class DefaultWebSecurityExpressionHandlerTests { @@ -97,21 +97,4 @@ public class DefaultWebSecurityExpressionHandlerTests { verify(trustResolver).isAnonymous(authentication); } - @Test - public void testDefaultRolePrefix() { - StaticApplicationContext appContext = new StaticApplicationContext(); - RootBeanDefinition bean = new RootBeanDefinition(GrantedAuthorityDefaults.class); - bean.getConstructorArgumentValues().addGenericArgumentValue("ROL_"); - appContext.registerBeanDefinition("authorityDefaults", bean); - handler.setApplicationContext(appContext); - - EvaluationContext ctx = handler.createEvaluationContext( - mock(Authentication.class), mock(FilterInvocation.class)); - ExpressionParser parser = handler.getExpressionParser(); - assertThat(parser.parseExpression("@authorityDefaults.getRolePrefix() == 'ROL_'").getValue( - ctx, Boolean.class)).isTrue(); - assertThat(parser.parseExpression("@authorityDefaults.rolePrefix == 'ROL_'").getValue(ctx, - Boolean.class)).isTrue(); - } - } diff --git a/web/src/test/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilterTests.java b/web/src/test/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilterTests.java index 62282fb082..339e4d42aa 100644 --- a/web/src/test/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilterTests.java @@ -36,9 +36,6 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.internal.WhiteboxImpl; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; @@ -46,13 +43,11 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.concurrent.DelegatingSecurityContextRunnable; -import org.springframework.security.config.GrantedAuthorityDefaults; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -422,30 +417,4 @@ public class SecurityContextHolderAwareRequestFilterTests { return this.requestCaptor.getValue(); } - @Test - public void testDefaultRolePrefix() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(FilterConfiguration.class); - context.refresh(); - - SecurityContextHolderAwareRequestFilter filter = context.getBean(SecurityContextHolderAwareRequestFilter.class); - GrantedAuthorityDefaults authorityDefaults = (GrantedAuthorityDefaults) ReflectionTestUtils.getField(filter, "rolePrefix"); - assertThat(authorityDefaults.getRolePrefix()).isEqualTo("ROL_"); - } - - @Configuration - static class FilterConfiguration { - - @Bean - public GrantedAuthorityDefaults authorityDefaults() { - return new GrantedAuthorityDefaults("ROL_"); - } - - @Bean - public SecurityContextHolderAwareRequestFilter requestFilter() { - return new SecurityContextHolderAwareRequestFilter(); - } - - } - }