diff --git a/config/src/main/java/org/springframework/security/config/BeanIds.java b/config/src/main/java/org/springframework/security/config/BeanIds.java index d4ae25e53d..fcf2e5fc1d 100644 --- a/config/src/main/java/org/springframework/security/config/BeanIds.java +++ b/config/src/main/java/org/springframework/security/config/BeanIds.java @@ -35,7 +35,9 @@ public abstract class BeanIds { */ public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager"; - /** External alias for FilterChainProxy bean, for use in web.xml files */ + /** + * External alias for FilterChainProxy bean, for use in web.xml files + */ public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain"; public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor"; diff --git a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java index 6c2cf3c5fd..b96b2ee872 100644 --- a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java @@ -33,7 +33,6 @@ public class DebugBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition debugPP = new RootBeanDefinition(SecurityDebugBeanFactoryPostProcessor.class); parserContext.getReaderContext().registerWithGeneratedName(debugPP); - return null; } diff --git a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java index 9273bee2af..9a11086870 100644 --- a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java +++ b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java @@ -75,17 +75,13 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { public SecurityNamespaceHandler() { String coreVersion = SpringSecurityCoreVersion.getVersion(); - Package pkg = SpringSecurityCoreVersion.class.getPackage(); - if (pkg == null || coreVersion == null) { this.logger.info("Couldn't determine package version information."); return; } - String version = pkg.getImplementationVersion(); this.logger.info("Spring Security 'config' module version is " + version); - if (version.compareTo(coreVersion) != 0) { this.logger.error( "You are running with different versions of the Spring Security 'core' and 'config' modules"); @@ -95,44 +91,37 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { @Override public BeanDefinition parse(Element element, ParserContext pc) { if (!namespaceMatchesVersion(element)) { - pc.getReaderContext().fatal( - "You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema " - + "with Spring Security 5.4. Please update your schema declarations to the 5.4 schema.", - element); + pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or " + + "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema " + + "with Spring Security 5.4. Please update your schema declarations to the 5.4 schema.", element); } String name = pc.getDelegate().getLocalName(element); BeanDefinitionParser parser = this.parsers.get(name); - if (parser == null) { // SEC-1455. Load parsers when required, not just on init(). loadParsers(); } - - if (parser == null) { - if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) - || Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) { - reportMissingWebClasses(name, pc, element); - } - else { - reportUnsupportedNodeType(name, pc, element); - } - - return null; + if (parser != null) { + return parser.parse(element, pc); } - - return parser.parse(element, pc); + if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) + || Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) { + reportMissingWebClasses(name, pc, element); + } + else { + reportUnsupportedNodeType(name, pc, element); + } + return null; } @Override public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) { String name = pc.getDelegate().getLocalName(node); - - // We only handle elements if (node instanceof Element) { + // We only handle elements if (Elements.INTERCEPT_METHODS.equals(name)) { return this.interceptMethodsBDD.decorate(node, definition, pc); } - if (Elements.FILTER_CHAIN_MAP.equals(name)) { if (this.filterChainMapBDD == null) { loadParsers(); @@ -143,9 +132,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { return this.filterChainMapBDD.decorate(node, definition, pc); } } - reportUnsupportedNodeType(name, pc, node); - return null; } @@ -162,9 +149,9 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { // no details available pc.getReaderContext().fatal(errorMessage, node); } - catch (Throwable cause) { + catch (Throwable ex) { // provide details on why it could not be loaded - pc.getReaderContext().fatal(errorMessage, node, cause); + pc.getReaderContext().fatal(errorMessage, node, ex); } } @@ -185,25 +172,28 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { this.parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser()); this.parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser()); - - // Only load the web-namespace parsers if the web classes are available if (ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader())) { - this.parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser()); - this.parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); - this.parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); - this.parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, - new FilterInvocationSecurityMetadataSourceParser()); - this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser()); - this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator(); - this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser()); + loadWebParsers(); } - if (ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) { - this.parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, - new WebSocketMessageBrokerSecurityBeanDefinitionParser()); + loadWebSocketParsers(); } } + private void loadWebParsers() { + this.parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser()); + this.parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); + this.parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); + this.parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser()); + this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser()); + this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator(); + this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser()); + } + + private void loadWebSocketParsers() { + this.parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, new WebSocketMessageBrokerSecurityBeanDefinitionParser()); + } + /** * Check that the schema location declared in the source file being parsed matches the * Spring Security version. The old 2.0 schema is not compatible with the 3.1 parser, diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java index 11da1c8148..b9d6ebed1e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java @@ -99,18 +99,16 @@ public abstract class AbstractConfiguredSecurityBuilder> void add(C configurer) { Assert.notNull(configurer, "configurer cannot be null"); - Class> clazz = (Class>) configurer .getClass(); synchronized (this.configurers) { if (this.buildState.isConfigured()) { throw new IllegalStateException("Cannot apply " + configurer + " to already built object"); } - List> configs = this.allowConfigurersOfSameType ? this.configurers.get(clazz) - : null; - if (configs == null) { - configs = new ArrayList<>(1); + List> configs = null; + if (this.allowConfigurersOfSameType) { + configs = this.configurers.get(clazz); } + configs = (configs != null) ? configs : new ArrayList<>(1); configs.add(configurer); this.configurers.put(clazz, configs); if (this.buildState.isInitializing()) { @@ -239,9 +236,8 @@ public abstract class AbstractConfiguredSecurityBuilder "Only one configurer expected for type " + clazz + ", but got " + configs); return (C) configs.get(0); } @@ -257,9 +253,8 @@ public abstract class AbstractConfiguredSecurityBuilder "Only one configurer expected for type " + clazz + ", but got " + configs); return (C) configs.get(0); } @@ -301,21 +296,14 @@ public abstract class AbstractConfiguredSecurityBuilder> configurers = getConfigurers(); - for (SecurityConfigurer configurer : configurers) { configurer.init((B) this); } - for (SecurityConfigurer configurer : this.configurersAddedInInitializing) { configurer.init((B) this); } @@ -359,7 +345,6 @@ public abstract class AbstractConfiguredSecurityBuilder> configurers = getConfigurers(); - for (SecurityConfigurer configurer : configurers) { configurer.configure((B) this); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java index a36d983c5c..fd25c16d12 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.core.GenericTypeResolver; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.util.Assert; /** * A base class for {@link SecurityConfigurer} that allows subclasses to only implement @@ -63,9 +64,7 @@ public abstract class SecurityConfigurerAdapter> * @throws IllegalStateException if {@link SecurityBuilder} is null */ protected final B getBuilder() { - if (this.securityBuilder == null) { - throw new IllegalStateException("securityBuilder cannot be null"); - } + Assert.state(this.securityBuilder != null, "securityBuilder cannot be null"); return this.securityBuilder; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java index c2ed0a82ce..821a88d3d2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java @@ -36,6 +36,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.log.LogMessage; import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.ObjectPostProcessor; @@ -80,7 +81,6 @@ public class AuthenticationConfiguration { LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context); AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, AuthenticationEventPublisher.class); - DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder( objectPostProcessor, defaultPasswordEncoder); if (authenticationEventPublisher != null) { @@ -115,17 +115,13 @@ public class AuthenticationConfiguration { if (this.buildingAuthenticationManager.getAndSet(true)) { return new AuthenticationManagerDelegator(authBuilder); } - for (GlobalAuthenticationConfigurerAdapter config : this.globalAuthConfigurers) { authBuilder.apply(config); } - this.authenticationManager = authBuilder.build(); - if (this.authenticationManager == null) { this.authenticationManager = getAuthenticationManagerBean(); } - this.authenticationManagerInitialized = true; return this.authenticationManager; } @@ -154,20 +150,7 @@ public class AuthenticationConfiguration { if (beanNamesForType.length == 0) { return null; } - String beanName; - if (beanNamesForType.length > 1) { - List primaryBeanNames = getPrimaryBeanNames(beanNamesForType); - - Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length + " beans for type " - + interfaceName + ", but none marked as primary"); - Assert.isTrue(primaryBeanNames.size() == 1, () -> "Found " + primaryBeanNames.size() + " beans for type " - + interfaceName + " marked as primary"); - beanName = primaryBeanNames.get(0); - } - else { - beanName = beanNamesForType[0]; - } - + String beanName = getBeanName(interfaceName, beanNamesForType); lazyTargetSource.setTargetBeanName(beanName); lazyTargetSource.setBeanFactory(this.applicationContext); ProxyFactoryBean proxyFactory = new ProxyFactoryBean(); @@ -176,6 +159,18 @@ public class AuthenticationConfiguration { return (T) proxyFactory.getObject(); } + private String getBeanName(Class interfaceName, String[] beanNamesForType) { + if (beanNamesForType.length == 1) { + return beanNamesForType[0]; + } + List primaryBeanNames = getPrimaryBeanNames(beanNamesForType); + Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length + " beans for type " + + interfaceName + ", but none marked as primary"); + Assert.isTrue(primaryBeanNames.size() == 1, + () -> "Found " + primaryBeanNames.size() + " beans for type " + interfaceName + " marked as primary"); + return primaryBeanNames.get(0); + } + private List getPrimaryBeanNames(String[] beanNamesForType) { List list = new ArrayList<>(); if (!(this.applicationContext instanceof ConfigurableApplicationContext)) { @@ -217,9 +212,7 @@ public class AuthenticationConfiguration { public void init(AuthenticationManagerBuilder auth) { Map beansWithAnnotation = this.context .getBeansWithAnnotation(EnableGlobalAuthentication.class); - if (logger.isDebugEnabled()) { - logger.debug("Eagerly initializing " + beansWithAnnotation); - } + logger.debug(LogMessage.format("Eagerly initializing %s", beansWithAnnotation)); } } @@ -249,14 +242,12 @@ public class AuthenticationConfiguration { if (this.delegate != null) { return this.delegate.authenticate(authentication); } - synchronized (this.delegateMonitor) { if (this.delegate == null) { this.delegate = this.delegateBuilder.getObject(); this.delegateBuilder = null; } } - return this.delegate.authenticate(authentication); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java index 3853c9c4e3..3958699f4b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java @@ -58,7 +58,6 @@ class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthen if (authenticationProvider == null) { return; } - auth.authenticationProvider(authenticationProvider); } @@ -72,7 +71,6 @@ class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthen if (beanNames.length != 1) { return null; } - return InitializeAuthenticationProviderBeanManagerConfigurer.this.context.getBean(beanNames[0], type); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java index f14776f184..07fff8886b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java @@ -63,10 +63,8 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon if (userDetailsService == null) { return; } - PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class); - DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); if (passwordEncoder != null) { @@ -76,7 +74,6 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon provider.setUserDetailsPasswordService(passwordManager); } provider.afterPropertiesSet(); - auth.authenticationProvider(provider); } @@ -89,7 +86,6 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon if (beanNames.length != 1) { return null; } - return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type); } 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 389a39eda6..ac956837b7 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 @@ -93,9 +93,7 @@ public class LdapAuthenticationProviderConfigurer, C @Override public void configure(B builder) throws Exception { initUserDetailsService(); - super.configure(builder); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java index 9ca88e0b5c..7792ff44ce 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java @@ -91,8 +91,8 @@ final class AutowireBeanFactoryObjectPostProcessor try { disposable.destroy(); } - catch (Exception error) { - this.logger.error(error); + catch (Exception ex) { + this.logger.error(ex); } } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java index 773ea42614..b2c44c9280 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java @@ -46,15 +46,12 @@ class GlobalMethodSecurityAspectJAutoProxyRegistrar implements ImportBeanDefinit */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - BeanDefinition interceptor = registry.getBeanDefinition("methodSecurityInterceptor"); - BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); aspect.setFactoryMethod("aspectOf"); aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); aspect.addPropertyValue("securityInterceptor", interceptor); - registry.registerBeanDefinition("annotationSecurityAspect$0", aspect.getBeanDefinition()); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java index 5dda0b0f1f..89c713062d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java @@ -92,11 +92,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit private static final Log logger = LogFactory.getLog(GlobalMethodSecurityConfiguration.class); private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { + @Override public T postProcess(T object) { throw new IllegalStateException(ObjectPostProcessor.class.getName() + " is a required bean. Ensure you have used @" + EnableGlobalMethodSecurity.class.getName()); } + }; private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler(); @@ -145,7 +147,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit if (runAsManager != null) { this.methodSecurityInterceptor.setRunAsManager(runAsManager); } - return this.methodSecurityInterceptor; } @@ -157,22 +158,18 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit catch (Exception ex) { throw new RuntimeException(ex); } - PermissionEvaluator permissionEvaluator = getSingleBeanOrNull(PermissionEvaluator.class); if (permissionEvaluator != null) { this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluator); } - RoleHierarchy roleHierarchy = getSingleBeanOrNull(RoleHierarchy.class); if (roleHierarchy != null) { this.defaultMethodExpressionHandler.setRoleHierarchy(roleHierarchy); } - AuthenticationTrustResolver trustResolver = getSingleBeanOrNull(AuthenticationTrustResolver.class); if (trustResolver != null) { this.defaultMethodExpressionHandler.setTrustResolver(trustResolver); } - GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaults != null) { this.defaultMethodExpressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()); @@ -315,12 +312,8 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit this.auth = new AuthenticationManagerBuilder(this.objectPostProcessor); this.auth.authenticationEventPublisher(eventPublisher); configure(this.auth); - if (this.disableAuthenticationRegistry) { - this.authenticationManager = getAuthenticationConfiguration().getAuthenticationManager(); - } - else { - this.authenticationManager = this.auth.build(); - } + this.authenticationManager = (this.disableAuthenticationRegistry) + ? getAuthenticationConfiguration().getAuthenticationManager() : this.auth.build(); } return this.authenticationManager; } @@ -353,17 +346,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit if (customMethodSecurityMetadataSource != null) { sources.add(customMethodSecurityMetadataSource); } - boolean hasCustom = customMethodSecurityMetadataSource != null; boolean isPrePostEnabled = prePostEnabled(); boolean isSecuredEnabled = securedEnabled(); boolean isJsr250Enabled = jsr250Enabled(); - - if (!isPrePostEnabled && !isSecuredEnabled && !isJsr250Enabled && !hasCustom) { - throw new IllegalStateException("In the composition of all global method configuration, " - + "no annotation support was actually activated"); - } - + Assert.state(isPrePostEnabled || isSecuredEnabled || isJsr250Enabled || hasCustom, + "In the composition of all global method configuration, " + + "no annotation support was actually activated"); if (isPrePostEnabled) { sources.add(new PrePostAnnotationSecurityMetadataSource(attributeFactory)); } @@ -441,10 +430,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit return enableMethodSecurity().getBoolean("jsr250Enabled"); } - private int order() { - return (Integer) enableMethodSecurity().get("order"); - } - private boolean isAspectJ() { return enableMethodSecurity().getEnum("mode") == AdviceMode.ASPECTJ; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java index 91b9b82180..516835b0a4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java @@ -45,35 +45,27 @@ final class GlobalMethodSecuritySelector implements ImportSelector { AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationAttributes); Assert.notNull(attributes, () -> String.format("@%s is not present on importing class '%s' as expected", annoType.getSimpleName(), importingClassMetadata.getClassName())); - // TODO would be nice if could use BeanClassLoaderAware (does not work) Class importingClass = ClassUtils.resolveClassName(importingClassMetadata.getClassName(), ClassUtils.getDefaultClassLoader()); boolean skipMethodSecurityConfiguration = GlobalMethodSecurityConfiguration.class .isAssignableFrom(importingClass); - AdviceMode mode = attributes.getEnum("mode"); boolean isProxy = AdviceMode.PROXY == mode; String autoProxyClassName = isProxy ? AutoProxyRegistrar.class.getName() : GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName(); - boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); - List classNames = new ArrayList<>(4); if (isProxy) { classNames.add(MethodSecurityMetadataSourceAdvisorRegistrar.class.getName()); } - classNames.add(autoProxyClassName); - if (!skipMethodSecurityConfiguration) { classNames.add(GlobalMethodSecurityConfiguration.class.getName()); } - if (jsr250Enabled) { classNames.add(Jsr250MetadataSourceConfiguration.class.getName()); } - return classNames.toArray(new String[0]); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java index ba3546cf70..84a33b00cd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java @@ -42,21 +42,18 @@ class MethodSecurityMetadataSourceAdvisorRegistrar implements ImportBeanDefiniti */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - BeanDefinitionBuilder advisor = BeanDefinitionBuilder .rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisor.addConstructorArgValue("methodSecurityInterceptor"); advisor.addConstructorArgReference("methodSecurityMetadataSource"); advisor.addConstructorArgValue("methodSecurityMetadataSource"); - MultiValueMap attributes = importingClassMetadata .getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName()); Integer order = (Integer) attributes.getFirst("order"); if (order != null) { advisor.addPropertyValue("order", order); } - registry.registerBeanDefinition("metaDataSourceAdvisor", advisor.getBeanDefinition()); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java index 102795da16..e66dec4d6e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java @@ -72,11 +72,9 @@ class ReactiveMethodSecurityConfiguration implements ImportAware { @Bean PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(AbstractMethodSecurityMetadataSource source, MethodSecurityExpressionHandler handler) { - ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice(handler); ExpressionBasedPreInvocationAdvice preAdvice = new ExpressionBasedPreInvocationAdvice(); preAdvice.setExpressionHandler(handler); - return new PrePostAdviceReactiveMethodInterceptor(source, preAdvice, postAdvice); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java index eee357e655..17e350e5f2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java @@ -31,12 +31,10 @@ class ReactiveMethodSecuritySelector extends AdviceModeImportSelector payloadInterceptors() { List result = new ArrayList<>(this.payloadInterceptors); - if (this.basicAuthSpec != null) { result.add(this.basicAuthSpec.build()); } @@ -213,7 +212,6 @@ public class RSocketSecurity { result.addAll(this.jwtSpec.build()); } result.add(anonymous()); - if (this.authorizePayload != null) { result.add(this.authorizePayload.build()); } @@ -260,6 +258,9 @@ public class RSocketSecurity { private ReactiveAuthenticationManager authenticationManager; + private SimpleAuthenticationSpec() { + } + public SimpleAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; @@ -280,15 +281,15 @@ public class RSocketSecurity { return result; } - private SimpleAuthenticationSpec() { - } - } public final class BasicAuthenticationSpec { private ReactiveAuthenticationManager authenticationManager; + private BasicAuthenticationSpec() { + } + public BasicAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; @@ -308,15 +309,15 @@ public class RSocketSecurity { return result; } - private BasicAuthenticationSpec() { - } - } public final class JwtSpec { private ReactiveAuthenticationManager authenticationManager; + private JwtSpec() { + } + public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; @@ -339,17 +340,12 @@ public class RSocketSecurity { AuthenticationPayloadInterceptor legacy = new AuthenticationPayloadInterceptor(manager); legacy.setAuthenticationConverter(new BearerPayloadExchangeConverter()); legacy.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); - AuthenticationPayloadInterceptor standard = new AuthenticationPayloadInterceptor(manager); standard.setAuthenticationConverter(new AuthenticationPayloadExchangeConverter()); standard.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); - return Arrays.asList(standard, legacy); } - private JwtSpec() { - } - } public class AuthorizePayloadsSpec { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java index 054896575c..e20d71054d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java @@ -170,7 +170,6 @@ public abstract class AbstractRequestMatcherRegistry { for (String mvcPattern : mvcPatterns) { MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern); opp.postProcess(matcher); - if (method != null) { matcher.setMethod(method); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java index d143aab14c..9c07581daa 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java @@ -46,6 +46,7 @@ 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.util.Assert; import org.springframework.web.filter.CorsFilter; /** @@ -138,10 +139,7 @@ final class FilterComparator implements Comparator, Serializable { */ void registerAfter(Class filter, Class afterFilter) { Integer position = getOrder(afterFilter); - if (position == null) { - throw new IllegalArgumentException("Cannot register after unregistered Filter " + afterFilter); - } - + Assert.notNull(position, () -> "Cannot register after unregistered Filter " + afterFilter); put(filter, position + 1); } @@ -153,10 +151,7 @@ final class FilterComparator implements Comparator, Serializable { */ void registerAt(Class filter, Class atFilter) { Integer position = getOrder(atFilter); - if (position == null) { - throw new IllegalArgumentException("Cannot register after unregistered Filter " + atFilter); - } - + Assert.notNull(position, () -> "Cannot register after unregistered Filter " + atFilter); put(filter, position); } @@ -169,10 +164,7 @@ final class FilterComparator implements Comparator, Serializable { */ void registerBefore(Class filter, Class beforeFilter) { Integer position = getOrder(beforeFilter); - if (position == null) { - throw new IllegalArgumentException("Cannot register after unregistered Filter " + beforeFilter); - } - + Assert.notNull(position, () -> "Cannot register after unregistered Filter " + beforeFilter); put(filter, position - 1); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index 5ff35ec68f..78cbb2a4f3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -308,20 +308,17 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder()); - + http.csrf(withDefaults()); + http.addFilter(new WebAsyncManagerIntegrationFilter()); + http.exceptionHandling(withDefaults()); + http.headers(withDefaults()); + http.sessionManagement(withDefaults()); + http.securityContext(withDefaults()); + http.requestCache(withDefaults()); + http.anonymous(withDefaults()); + http.servletApi(withDefaults()); + http.logout(withDefaults()); + http.apply(new DefaultLoginPageConfigurer<>()); return http; } private AuthenticationManager authenticationManager() throws Exception { - if (this.authenticationManager != null) { - return this.authenticationManager; - } - else { - return this.authenticationConfiguration.getAuthenticationManager(); - } + return (this.authenticationManager != null) ? this.authenticationManager + : this.authenticationConfiguration.getAuthenticationManager(); } private Map, Object> createSharedObjects() { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java index 9b6e11ec87..80f4ffa6b6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java @@ -54,12 +54,12 @@ final class OAuth2ClientConfiguration { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", - getClass().getClassLoader()); - - return webmvcPresent ? new String[] { - "org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" } - : new String[] {}; + if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", + getClass().getClassLoader())) { + return new String[0]; + } + return new String[] { "org.springframework.security.config.annotation.web.configuration." + + "OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" }; } } @@ -114,7 +114,6 @@ final class OAuth2ClientConfiguration { if (this.authorizedClientManager != null) { return this.authorizedClientManager; } - OAuth2AuthorizedClientManager authorizedClientManager = null; if (this.clientRegistrationRepository != null && this.authorizedClientRepository != null) { if (this.accessTokenResponseClient != null) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java index 058fc630db..79eeb478d5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java @@ -22,6 +22,7 @@ import java.util.Set; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; /** * Used by {@link EnableWebSecurity} to conditionally import: @@ -45,29 +46,25 @@ final class OAuth2ImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { Set imports = new LinkedHashSet<>(); - - boolean oauth2ClientPresent = ClassUtils.isPresent( - "org.springframework.security.oauth2.client.registration.ClientRegistration", - getClass().getClassLoader()); + ClassLoader classLoader = getClass().getClassLoader(); + boolean oauth2ClientPresent = ClassUtils + .isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration", classLoader); + boolean webfluxPresent = ClassUtils + .isPresent("org.springframework.web.reactive.function.client.ExchangeFilterFunction", classLoader); + boolean oauth2ResourceServerPresent = ClassUtils + .isPresent("org.springframework.security.oauth2.server.resource.BearerTokenError", classLoader); if (oauth2ClientPresent) { imports.add("org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration"); } - - boolean webfluxPresent = ClassUtils.isPresent( - "org.springframework.web.reactive.function.client.ExchangeFilterFunction", getClass().getClassLoader()); if (webfluxPresent && oauth2ClientPresent) { imports.add( "org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); } - - boolean oauth2ResourceServerPresent = ClassUtils.isPresent( - "org.springframework.security.oauth2.server.resource.BearerTokenError", getClass().getClassLoader()); if (webfluxPresent && oauth2ResourceServerPresent) { imports.add( "org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); } - - return imports.toArray(new String[0]); + return StringUtils.toStringArray(imports); } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java index 2e59665ff4..2783cb358b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java @@ -71,7 +71,6 @@ class SecurityReactorContextConfiguration { public void afterPropertiesSet() throws Exception { Function, ? extends Publisher> lifter = Operators .liftPublisher((pub, sub) -> createSubscriberIfNecessary(sub)); - Hooks.onLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY, (pub) -> { if (!contextAttributesAvailable()) { // No need to decorate so return original Publisher @@ -112,7 +111,6 @@ class SecurityReactorContextConfiguration { if (authentication == null && servletRequest == null) { return Collections.emptyMap(); } - Map contextAttributes = new HashMap<>(); if (servletRequest != null) { contextAttributes.put(HttpServletRequest.class, servletRequest); @@ -139,17 +137,17 @@ class SecurityReactorContextConfiguration { SecurityReactorContextSubscriber(CoreSubscriber delegate, Map attributes) { this.delegate = delegate; - Context currentContext = this.delegate.currentContext(); - Context context; - if (currentContext.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) { - context = currentContext; - } - else { - context = currentContext.put(SECURITY_CONTEXT_ATTRIBUTES, attributes); - } + Context context = getOrPutContext(attributes, this.delegate.currentContext()); this.context = context; } + private Context getOrPutContext(Map attributes, Context currentContext) { + if (currentContext.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) { + return currentContext; + } + return currentContext.put(SECURITY_CONTEXT_ATTRIBUTES, attributes); + } + @Override public Context currentContext() { return this.context; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java index 4ff31b81d0..fee0fd6162 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java @@ -32,12 +32,11 @@ class SpringWebMvcImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", - getClass().getClassLoader()); - return webmvcPresent - ? new String[] { - "org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration" } - : new String[] {}; + if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader())) { + return new String[0]; + } + return new String[] { + "org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration" }; } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index 0e72157de2..db63fcf82b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java @@ -58,7 +58,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex argumentResolvers.add(authenticationPrincipalResolver); argumentResolvers .add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver()); - CurrentSecurityContextArgumentResolver currentSecurityContextArgumentResolver = new CurrentSecurityContextArgumentResolver(); currentSecurityContextArgumentResolver.setBeanResolver(this.beanResolver); argumentResolvers.add(currentSecurityContextArgumentResolver); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java index 2294bdc25d..27fc4ba5e1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java @@ -50,6 +50,7 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; +import org.springframework.util.Assert; /** * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web @@ -101,10 +102,8 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa public Filter springSecurityFilterChain() throws Exception { boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty(); boolean hasFilterChain = !this.securityFilterChains.isEmpty(); - if (hasConfigurers && hasFilterChain) { - throw new IllegalStateException( - "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain." + "Please select just one."); - } + Assert.state(!(hasConfigurers && hasFilterChain), + "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one."); if (!hasConfigurers && !hasFilterChain) { WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor .postProcess(new WebSecurityConfigurerAdapter() { @@ -152,9 +151,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa if (this.debugEnabled != null) { this.webSecurity.debug(this.debugEnabled); } - webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE); - Integer previousOrder = null; Object previousConfig = null; for (SecurityConfigurer config : webSecurityConfigurers) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java index fd66c8bf5a..61609ede2a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configuration; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -200,34 +199,17 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu if (this.http != null) { return this.http; } - AuthenticationEventPublisher eventPublisher = getAuthenticationEventPublisher(); this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher); - AuthenticationManager authenticationManager = authenticationManager(); this.authenticationBuilder.parentAuthenticationManager(authenticationManager); Map, Object> sharedObjects = createSharedObjects(); - this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects); if (!this.disableDefaults) { - // @formatter:off - this.http - .csrf().and() - .addFilter(new WebAsyncManagerIntegrationFilter()) - .exceptionHandling().and() - .headers().and() - .sessionManagement().and() - .securityContext().and() - .requestCache().and() - .anonymous().and() - .servletApi().and() - .apply(new DefaultLoginPageConfigurer<>()).and() - .logout(); - // @formatter:on + applyDefaultConfiguration(this.http); ClassLoader classLoader = this.context.getClassLoader(); List defaultHttpConfigurers = SpringFactoriesLoader .loadFactories(AbstractHttpConfigurer.class, classLoader); - for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) { this.http.apply(configurer); } @@ -236,6 +218,20 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu return this.http; } + private void applyDefaultConfiguration(HttpSecurity http) throws Exception { + http.csrf(); + http.addFilter(new WebAsyncManagerIntegrationFilter()); + http.exceptionHandling(); + http.headers(); + http.sessionManagement(); + http.securityContext(); + http.requestCache(); + http.anonymous(); + http.servletApi(); + http.apply(new DefaultLoginPageConfigurer<>()); + http.logout(); + } + /** * Override this method to expose the {@link AuthenticationManager} from * {@link #configure(AuthenticationManagerBuilder)} to be exposed as a Bean. For @@ -315,8 +311,8 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu } @Override - public void init(final WebSecurity web) throws Exception { - final HttpSecurity http = getHttp(); + public void init(WebSecurity web) throws Exception { + HttpSecurity http = getHttp(); web.addSecurityFilterChainBuilder(http).postBuildAction(() -> { FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); web.securityInterceptor(securityInterceptor); @@ -354,17 +350,11 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu * @throws Exception if an error occurs */ protected void configure(HttpSecurity http) throws Exception { - this.logger.debug( - "Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); - - // @formatter:off - http - .authorizeRequests() - .anyRequest().authenticated() - .and() - .formLogin().and() - .httpBasic(); - // @formatter:on + this.logger.debug("Using default configure(HttpSecurity). " + + "If subclassed this will potentially override subclass configure(HttpSecurity)."); + http.authorizeRequests((requests) -> requests.anyRequest().authenticated()); + http.formLogin(); + http.httpBasic(); } /** @@ -378,14 +368,13 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu @Autowired public void setApplicationContext(ApplicationContext context) { this.context = context; - ObjectPostProcessor objectPostProcessor = context.getBean(ObjectPostProcessor.class); LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(context); - this.authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, passwordEncoder); this.localConfigureAuthenticationBldr = new DefaultPasswordEncoderAuthenticationManagerBuilder( objectPostProcessor, passwordEncoder) { + @Override public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { WebSecurityConfigurerAdapter.this.authenticationBuilder.eraseCredentials(eraseCredentials); @@ -398,6 +387,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu WebSecurityConfigurerAdapter.this.authenticationBuilder.authenticationEventPublisher(eventPublisher); return super.authenticationEventPublisher(eventPublisher); } + }; } @@ -458,10 +448,8 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu private final Object delegateMonitor = new Object(); UserDetailsServiceDelegator(List delegateBuilders) { - if (delegateBuilders.contains(null)) { - throw new IllegalArgumentException( - "delegateBuilders cannot contain null values. Got " + delegateBuilders); - } + Assert.isTrue(!delegateBuilders.contains(null), + () -> "delegateBuilders cannot contain null values. Got " + delegateBuilders); this.delegateBuilders = delegateBuilders; } @@ -470,7 +458,6 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu if (this.delegate != null) { return this.delegate.loadUserByUsername(username); } - synchronized (this.delegateMonitor) { if (this.delegate == null) { for (AuthenticationManagerBuilder delegateBuilder : this.delegateBuilders) { @@ -479,14 +466,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu break; } } - if (this.delegate == null) { throw new IllegalStateException("UserDetailsService is required."); } this.delegateBuilders = null; } } - return this.delegate.loadUserByUsername(username); } @@ -524,14 +509,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu if (this.delegate != null) { return this.delegate.authenticate(authentication); } - synchronized (this.delegateMonitor) { if (this.delegate == null) { this.delegate = this.delegateBuilder.getObject(); this.delegateBuilder = null; } } - return this.delegate.authenticate(authentication); } @@ -542,19 +525,18 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu } private static void validateBeanCycle(Object auth, Set beanNames) { - if (auth != null && !beanNames.isEmpty()) { - if (auth instanceof Advised) { - Advised advised = (Advised) auth; - TargetSource targetSource = advised.getTargetSource(); - if (targetSource instanceof LazyInitTargetSource) { - LazyInitTargetSource lits = (LazyInitTargetSource) targetSource; - if (beanNames.contains(lits.getTargetBeanName())) { - throw new FatalBeanException( - "A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication."); - } - } - } - beanNames = Collections.emptySet(); + if (auth == null || beanNames.isEmpty() || !(auth instanceof Advised)) { + return; + } + TargetSource targetSource = ((Advised) auth).getTargetSource(); + if (!(targetSource instanceof LazyInitTargetSource)) { + return; + } + LazyInitTargetSource lits = (LazyInitTargetSource) targetSource; + if (beanNames.contains(lits.getTargetBeanName())) { + throw new FatalBeanException( + "A dependency cycle was detected when trying to resolve the AuthenticationManager. " + + "Please ensure you have configured authentication."); } } @@ -634,7 +616,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu try { return this.applicationContext.getBean(type); } - catch (NoSuchBeanDefinitionException notFound) { + catch (NoSuchBeanDefinitionException ex) { return null; } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java index 4365785385..34cd345311 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java @@ -253,15 +253,12 @@ public abstract class AbstractAuthenticationFilterConfigurer logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class); + LogoutConfigurer logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class); if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) { logoutConfigurer.logoutSuccessUrl(this.loginPage + "?logout"); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java index 9385feb21e..12b41b5c42 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java @@ -24,6 +24,7 @@ import java.util.List; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry; import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.util.Assert; /** * A base class for registering {@link RequestMatcher}'s. For example, it might allow for @@ -102,11 +103,8 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends A * {@link ConfigAttribute} instances. Cannot be null. */ final LinkedHashMap> createRequestMap() { - if (this.unmappedMatchers != null) { - throw new IllegalStateException("An incomplete mapping was found for " + this.unmappedMatchers - + ". Try completing it with something like requestUrls()..hasRole('USER')"); - } - + Assert.state(this.unmappedMatchers == null, () -> "An incomplete mapping was found for " + this.unmappedMatchers + + ". Try completing it with something like requestUrls()..hasRole('USER')"); LinkedHashMap> requestMap = new LinkedHashMap<>(); for (UrlMapping mapping : getUrlMappings()) { RequestMatcher matcher = mapping.getRequestMatcher(); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java index 0881921efb..4144d5e840 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java @@ -28,7 +28,6 @@ import org.springframework.security.web.DefaultSecurityFilterChain; * {@link HttpSecurity}. * * @author Rob Winch - * */ public abstract class AbstractHttpConfigurer, B extends HttpSecurityBuilder> extends SecurityConfigurerAdapter { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java index c798212069..19fc8ae0ca 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java @@ -105,13 +105,10 @@ public final class ChannelSecurityConfigurer> ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl(); channelDecisionManager.setChannelProcessors(getChannelProcessors(http)); channelDecisionManager = postProcess(channelDecisionManager); - this.channelFilter.setChannelDecisionManager(channelDecisionManager); - DefaultFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = new DefaultFilterInvocationSecurityMetadataSource( this.requestMap); this.channelFilter.setSecurityMetadataSource(filterInvocationSecurityMetadataSource); - this.channelFilter = postProcess(this.channelFilter); http.addFilter(this.channelFilter); } @@ -120,28 +117,25 @@ public final class ChannelSecurityConfigurer> if (this.channelProcessors != null) { return this.channelProcessors; } - InsecureChannelProcessor insecureChannelProcessor = new InsecureChannelProcessor(); SecureChannelProcessor secureChannelProcessor = new SecureChannelProcessor(); - PortMapper portMapper = http.getSharedObject(PortMapper.class); if (portMapper != null) { RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint(); httpEntryPoint.setPortMapper(portMapper); insecureChannelProcessor.setEntryPoint(httpEntryPoint); - RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint(); httpsEntryPoint.setPortMapper(portMapper); secureChannelProcessor.setEntryPoint(httpsEntryPoint); } insecureChannelProcessor = postProcess(insecureChannelProcessor); secureChannelProcessor = postProcess(secureChannelProcessor); - return Arrays.asList(insecureChannelProcessor, secureChannelProcessor); + return Arrays.asList(insecureChannelProcessor, secureChannelProcessor); } private ChannelRequestMatcherRegistry addAttribute(String attribute, List matchers) { for (RequestMatcher matcher : matchers) { - Collection attrs = Arrays.asList(new SecurityConfig(attribute)); + Collection attrs = Arrays.asList(new SecurityConfig(attribute)); this.requestMap.put(matcher, attrs); } return this.REGISTRY; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java index 1e107cd659..f4002d799b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; @@ -63,12 +64,9 @@ public class CorsConfigurer> extends AbstractHt @Override public void configure(H http) { ApplicationContext context = http.getSharedObject(ApplicationContext.class); - CorsFilter corsFilter = getCorsFilter(context); - if (corsFilter == null) { - throw new IllegalStateException("Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a " - + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean."); - } + Assert.state(corsFilter != null, () -> "Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a " + + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean."); http.addFilter(corsFilter); } @@ -76,19 +74,16 @@ public class CorsConfigurer> extends AbstractHt if (this.configurationSource != null) { return new CorsFilter(this.configurationSource); } - boolean containsCorsFilter = context.containsBeanDefinition(CORS_FILTER_BEAN_NAME); if (containsCorsFilter) { return context.getBean(CORS_FILTER_BEAN_NAME, CorsFilter.class); } - boolean containsCorsSource = context.containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME); if (containsCorsSource) { CorsConfigurationSource configurationSource = context.getBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME, CorsConfigurationSource.class); return new CorsFilter(configurationSource); } - boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, context.getClassLoader()); if (mvcPresent) { return MvcCorsFilter.getMvcCorsFilter(context); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java index 6ead1c38c4..4e33f4bc7e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java @@ -289,7 +289,6 @@ public final class CsrfConfigurer> if (invalidSessionStrategy == null) { return defaultAccessDeniedHandler; } - InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler( invalidSessionStrategy); LinkedHashMap, AccessDeniedHandler> handlers = new LinkedHashMap<>(); @@ -307,9 +306,7 @@ public final class CsrfConfigurer> if (this.sessionAuthenticationStrategy != null) { return this.sessionAuthenticationStrategy; } - else { - return new CsrfAuthenticationStrategy(this.csrfTokenRepository); - } + return new CsrfAuthenticationStrategy(this.csrfTokenRepository); } /** diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java index 315e27a806..bf144dc56c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers; import java.util.Collections; import java.util.Map; -import java.util.function.Function; import javax.servlet.http.HttpServletRequest; @@ -76,18 +75,17 @@ public final class DefaultLoginPageConfigurer> @Override public void init(H http) { - Function> hiddenInputs = (request) -> { - CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); - if (token == null) { - return Collections.emptyMap(); - } - return Collections.singletonMap(token.getParameterName(), token.getToken()); - }; - this.loginPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs); - this.logoutPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs); + this.loginPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs); + this.logoutPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs); http.setSharedObject(DefaultLoginPageGeneratingFilter.class, this.loginPageGeneratingFilter); } + private Map hiddenInputs(HttpServletRequest request) { + CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); + return (token != null) ? Collections.singletonMap(token.getParameterName(), token.getToken()) + : Collections.emptyMap(); + } + @Override @SuppressWarnings("unchecked") public void configure(H http) { @@ -96,7 +94,6 @@ public final class DefaultLoginPageConfigurer> if (exceptionConf != null) { authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint(); } - if (this.loginPageGeneratingFilter.isEnabled() && authenticationEntryPoint == null) { this.loginPageGeneratingFilter = postProcess(this.loginPageGeneratingFilter); http.addFilter(this.loginPageGeneratingFilter); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java index bcdf904d70..949b833da4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java @@ -139,44 +139,40 @@ public final class ExpressionUrlAuthorizationConfigurer> requestMap = this.REGISTRY.createRequestMap(); - if (requestMap.isEmpty()) { - throw new IllegalStateException( - "At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); - } + Assert.state(!requestMap.isEmpty(), + "At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); } private SecurityExpressionHandler getExpressionHandler(H http) { - if (this.expressionHandler == null) { - DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); - AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); - if (trustResolver != null) { - defaultHandler.setTrustResolver(trustResolver); - } - ApplicationContext context = http.getSharedObject(ApplicationContext.class); - if (context != null) { - String[] roleHiearchyBeanNames = context.getBeanNamesForType(RoleHierarchy.class); - if (roleHiearchyBeanNames.length == 1) { - defaultHandler.setRoleHierarchy(context.getBean(roleHiearchyBeanNames[0], RoleHierarchy.class)); - } - String[] grantedAuthorityDefaultsBeanNames = context - .getBeanNamesForType(GrantedAuthorityDefaults.class); - if (grantedAuthorityDefaultsBeanNames.length == 1) { - GrantedAuthorityDefaults grantedAuthorityDefaults = context - .getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); - defaultHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()); - } - String[] permissionEvaluatorBeanNames = context.getBeanNamesForType(PermissionEvaluator.class); - if (permissionEvaluatorBeanNames.length == 1) { - PermissionEvaluator permissionEvaluator = context.getBean(permissionEvaluatorBeanNames[0], - PermissionEvaluator.class); - defaultHandler.setPermissionEvaluator(permissionEvaluator); - } - } - - this.expressionHandler = postProcess(defaultHandler); + if (this.expressionHandler != null) { + return this.expressionHandler; } - + DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); + if (trustResolver != null) { + defaultHandler.setTrustResolver(trustResolver); + } + ApplicationContext context = http.getSharedObject(ApplicationContext.class); + if (context != null) { + String[] roleHiearchyBeanNames = context.getBeanNamesForType(RoleHierarchy.class); + if (roleHiearchyBeanNames.length == 1) { + defaultHandler.setRoleHierarchy(context.getBean(roleHiearchyBeanNames[0], RoleHierarchy.class)); + } + String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); + if (grantedAuthorityDefaultsBeanNames.length == 1) { + GrantedAuthorityDefaults grantedAuthorityDefaults = context + .getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + defaultHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()); + } + String[] permissionEvaluatorBeanNames = context.getBeanNamesForType(PermissionEvaluator.class); + if (permissionEvaluatorBeanNames.length == 1) { + PermissionEvaluator permissionEvaluator = context.getBean(permissionEvaluatorBeanNames[0], + PermissionEvaluator.class); + defaultHandler.setPermissionEvaluator(permissionEvaluator); + } + } + this.expressionHandler = postProcess(defaultHandler); return this.expressionHandler; } @@ -187,10 +183,8 @@ public final class ExpressionUrlAuthorizationConfigurer "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'"); return "hasRole('ROLE_" + role + "')"; } @@ -210,9 +204,6 @@ public final class ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - /** - * @param context - */ private ExpressionInterceptUrlRegistry(ApplicationContext context) { setApplicationContext(context); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java index 0ed6cc1ca3..9d007ec7fa 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java @@ -329,7 +329,6 @@ public class HeadersConfigurer> Customizer contentSecurityCustomizer) { this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(); contentSecurityCustomizer.customize(this.contentSecurityPolicy); - return HeadersConfigurer.this; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java index e4f58325de..e45bb31a06 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java @@ -97,10 +97,8 @@ public final class HttpBasicConfigurer> */ public HttpBasicConfigurer() { realmName(DEFAULT_REALM); - LinkedHashMap entryPoints = new LinkedHashMap<>(); entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); - DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); defaultEntryPoint.setDefaultEntryPoint(this.basicAuthEntryPoint); this.authenticationEntryPoint = defaultEntryPoint; @@ -154,24 +152,19 @@ public final class HttpBasicConfigurer> if (contentNegotiationStrategy == null) { contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); } - MediaTypeRequestMatcher restMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML); restMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - MediaTypeRequestMatcher allMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.ALL); allMatcher.setUseEquals(true); - RequestMatcher notHtmlMatcher = new NegatedRequestMatcher( new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.TEXT_HTML)); RequestMatcher restNotHtmlMatcher = new AndRequestMatcher( Arrays.asList(notHtmlMatcher, restMatcher)); - RequestMatcher preferredMatcher = new OrRequestMatcher( Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher, allMatcher)); - registerDefaultEntryPoint(http, preferredMatcher); registerDefaultLogoutSuccessHandler(http, preferredMatcher); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java index 30928d0b24..bbd91f045c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java @@ -192,12 +192,8 @@ public final class JeeConfigurer> extends Abstr PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); authenticationProvider.setPreAuthenticatedUserDetailsService(getUserDetailsService()); authenticationProvider = postProcess(authenticationProvider); - - // @formatter:off - http - .authenticationProvider(authenticationProvider) - .setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint()); - // @formatter:on + http.authenticationProvider(authenticationProvider).setSharedObject(AuthenticationEntryPoint.class, + new Http403ForbiddenEntryPoint()); } @Override @@ -245,7 +241,6 @@ public final class JeeConfigurer> extends Abstr SimpleMappableAttributesRetriever rolesRetriever = new SimpleMappableAttributesRetriever(); rolesRetriever.setMappableAttributes(this.mappableRoles); detailsSource.setMappableRolesRetriever(rolesRetriever); - detailsSource = postProcess(detailsSource); return detailsSource; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java index 2567c4c3a5..a86d8339dc 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java @@ -276,7 +276,6 @@ public final class LogoutConfigurer> PermitAllSupport.permitAll(http, this.logoutSuccessUrl); PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http)); } - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http .getSharedObject(DefaultLoginPageGeneratingFilter.class); if (loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) { @@ -334,20 +333,28 @@ public final class LogoutConfigurer> return result; } - @SuppressWarnings("unchecked") private RequestMatcher getLogoutRequestMatcher(H http) { if (this.logoutRequestMatcher != null) { return this.logoutRequestMatcher; } - if (http.getConfigurer(CsrfConfigurer.class) != null) { - this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); - } - else { - this.logoutRequestMatcher = new OrRequestMatcher(new AntPathRequestMatcher(this.logoutUrl, "GET"), - new AntPathRequestMatcher(this.logoutUrl, "POST"), new AntPathRequestMatcher(this.logoutUrl, "PUT"), - new AntPathRequestMatcher(this.logoutUrl, "DELETE")); - } + this.logoutRequestMatcher = createLogoutRequestMatcher(http); return this.logoutRequestMatcher; } + @SuppressWarnings("unchecked") + private RequestMatcher createLogoutRequestMatcher(H http) { + RequestMatcher post = createLogoutRequestMatcher("POST"); + if (http.getConfigurer(CsrfConfigurer.class) != null) { + return post; + } + RequestMatcher get = createLogoutRequestMatcher("GET"); + RequestMatcher put = createLogoutRequestMatcher("PUT"); + RequestMatcher delete = createLogoutRequestMatcher("DELETE"); + return new OrRequestMatcher(get, post, put, delete); + } + + private RequestMatcher createLogoutRequestMatcher(String httpMethod) { + return new AntPathRequestMatcher(this.logoutUrl, httpMethod); + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java index c1c9152954..3af0eba172 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java @@ -22,6 +22,7 @@ import org.springframework.security.access.SecurityConfig; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry.UrlMapping; import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.util.Assert; /** * Configures non-null URL's to grant access to every URL @@ -47,11 +48,7 @@ final class PermitAllSupport { RequestMatcher... requestMatchers) { ExpressionUrlAuthorizationConfigurer configurer = http .getConfigurer(ExpressionUrlAuthorizationConfigurer.class); - - if (configurer == null) { - throw new IllegalStateException("permitAll only works with HttpSecurity.authorizeRequests()"); - } - + Assert.state(configurer != null, "permitAll only works with HttpSecurity.authorizeRequests()"); for (RequestMatcher matcher : requestMatchers) { if (matcher != null) { configurer.getRegistry().addMapping(0, new UrlMapping(matcher, @@ -72,15 +69,12 @@ final class PermitAllSupport { public boolean matches(HttpServletRequest request) { String uri = request.getRequestURI(); String query = request.getQueryString(); - if (query != null) { uri += "?" + query; } - if ("".equals(request.getContextPath())) { return uri.equals(this.processUrl); } - return uri.equals(request.getContextPath() + this.processUrl); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java index 1c54f5e440..d6d352995d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java @@ -35,6 +35,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter; import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices; import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter; +import org.springframework.util.Assert; /** * Configures Remember Me authentication. This typically involves the user checking a box @@ -275,11 +276,9 @@ public final class RememberMeConfigurer> if (logoutConfigurer != null && this.logoutHandler != null) { logoutConfigurer.addLogoutHandler(this.logoutHandler); } - RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider(key); authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); - initDefaultLoginFilter(http); } @@ -299,8 +298,8 @@ public final class RememberMeConfigurer> * time. */ private void validateInput() { - if (this.rememberMeServices != null && this.rememberMeCookieName != DEFAULT_REMEMBER_ME_NAME) { - throw new IllegalArgumentException("Can not set rememberMeCookieName " + "and custom rememberMeServices."); + if (this.rememberMeServices != null && !DEFAULT_REMEMBER_ME_NAME.equals(this.rememberMeCookieName)) { + throw new IllegalArgumentException("Can not set rememberMeCookieName and custom rememberMeServices."); } } @@ -406,11 +405,9 @@ public final class RememberMeConfigurer> if (this.userDetailsService == null) { this.userDetailsService = http.getSharedObject(UserDetailsService.class); } - if (this.userDetailsService == null) { - throw new IllegalStateException( - "userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName() - + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); - } + Assert.state(this.userDetailsService != null, + () -> "userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName() + + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); return this.userDetailsService; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index fcd5711e0e..e7eae3f283 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -145,12 +145,9 @@ public final class RequestCacheConfigurer> @SuppressWarnings("unchecked") private RequestMatcher createDefaultSavedRequestMatcher(H http) { RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.*")); - RequestMatcher notXRequestedWith = new NegatedRequestMatcher( new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); - boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null; - List matchers = new ArrayList<>(); if (isCsrfEnabled) { RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET"); @@ -161,7 +158,6 @@ public final class RequestCacheConfigurer> matchers.add(notXRequestedWith); matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA)); matchers.add(notMatchingMediaType(http, MediaType.TEXT_EVENT_STREAM)); - return new AndRequestMatcher(matchers); } @@ -170,7 +166,6 @@ public final class RequestCacheConfigurer> if (contentNegotiationStrategy == null) { contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); } - MediaTypeRequestMatcher mediaRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, mediaType); mediaRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); return new NegatedRequestMatcher(mediaRequest); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java index acd06c1221..2139961a00 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java @@ -82,7 +82,6 @@ public final class SecurityContextConfigurer> @Override @SuppressWarnings("unchecked") public void configure(H http) { - SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); if (securityContextRepository == null) { securityContextRepository = new HttpSessionSecurityContextRepository(); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index 59146667e4..86b9cc0275 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -316,7 +316,6 @@ public final class SessionManagementConfigurer> public void init(H http) { SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); boolean stateless = isStateless(); - if (securityContextRepository == null) { if (stateless) { http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); @@ -332,7 +331,6 @@ public final class SessionManagementConfigurer> http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository); } } - RequestCache requestCache = http.getSharedObject(RequestCache.class); if (requestCache == null) { if (stateless) { @@ -365,7 +363,6 @@ public final class SessionManagementConfigurer> sessionManagementFilter.setTrustResolver(trustResolver); } sessionManagementFilter = postProcess(sessionManagementFilter); - http.addFilter(sessionManagementFilter); if (isConcurrentSessionControlEnabled()) { ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http); @@ -378,13 +375,9 @@ public final class SessionManagementConfigurer> private ConcurrentSessionFilter createConcurrencyFilter(H http) { SessionInformationExpiredStrategy expireStrategy = getExpiredSessionStrategy(); SessionRegistry sessionRegistry = getSessionRegistry(http); - ConcurrentSessionFilter concurrentSessionFilter; - if (expireStrategy == null) { - concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry); - } - else { - concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry, expireStrategy); - } + ConcurrentSessionFilter concurrentSessionFilter = (expireStrategy != null) + ? new ConcurrentSessionFilter(sessionRegistry, expireStrategy) + : new ConcurrentSessionFilter(sessionRegistry); LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); if (logoutConfigurer != null) { List logoutHandlers = logoutConfigurer.getLogoutHandlers(); @@ -405,11 +398,9 @@ public final class SessionManagementConfigurer> if (this.invalidSessionStrategy != null) { return this.invalidSessionStrategy; } - if (this.invalidSessionUrl == null) { return null; } - this.invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(this.invalidSessionUrl); return this.invalidSessionStrategy; } @@ -418,11 +409,9 @@ public final class SessionManagementConfigurer> if (this.expiredSessionStrategy != null) { return this.expiredSessionStrategy; } - if (this.expiredUrl == null) { return null; } - this.expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy(this.expiredUrl); return this.expiredSessionStrategy; } @@ -431,11 +420,9 @@ public final class SessionManagementConfigurer> if (this.sessionAuthenticationFailureHandler != null) { return this.sessionAuthenticationFailureHandler; } - if (this.sessionAuthenticationErrorUrl == null) { return null; } - this.sessionAuthenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler( this.sessionAuthenticationErrorUrl); return this.sessionAuthenticationFailureHandler; @@ -449,7 +436,6 @@ public final class SessionManagementConfigurer> if (this.sessionPolicy != null) { return this.sessionPolicy; } - SessionCreationPolicy sessionPolicy = getBuilder().getSharedObject(SessionCreationPolicy.class); return (sessionPolicy != null) ? sessionPolicy : SessionCreationPolicy.IF_REQUIRED; } @@ -628,6 +614,9 @@ public final class SessionManagementConfigurer> */ public final class ConcurrencyControlConfigurer { + private ConcurrencyControlConfigurer() { + } + /** * Controls the maximum number of sessions for a user. The default is to allow any * number of users. @@ -699,9 +688,6 @@ public final class SessionManagementConfigurer> return SessionManagementConfigurer.this; } - private ConcurrencyControlConfigurer() { - } - } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java index 210eb8922a..4dd72aa947 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java @@ -89,10 +89,10 @@ import org.springframework.util.Assert; public final class UrlAuthorizationConfigurer> extends AbstractInterceptUrlConfigurer, H> { - private final StandardInterceptUrlRegistry REGISTRY; + private final StandardInterceptUrlRegistry registry; public UrlAuthorizationConfigurer(ApplicationContext context) { - this.REGISTRY = new StandardInterceptUrlRegistry(context); + this.registry = new StandardInterceptUrlRegistry(context); } /** @@ -101,7 +101,7 @@ public final class UrlAuthorizationConfigurer> * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations */ public StandardInterceptUrlRegistry getRegistry() { - return this.REGISTRY; + return this.registry; } /** @@ -136,7 +136,7 @@ public final class UrlAuthorizationConfigurer> */ @Override FilterInvocationSecurityMetadataSource createMetadataSource(H http) { - return new DefaultFilterInvocationSecurityMetadataSource(this.REGISTRY.createRequestMap()); + return new DefaultFilterInvocationSecurityMetadataSource(this.registry.createRequestMap()); } /** @@ -151,10 +151,10 @@ public final class UrlAuthorizationConfigurer> private StandardInterceptUrlRegistry addMapping(Iterable requestMatchers, Collection configAttributes) { for (RequestMatcher requestMatcher : requestMatchers) { - this.REGISTRY.addMapping( + this.registry.addMapping( new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes)); } - return this.REGISTRY; + return this.registry; } /** @@ -196,9 +196,6 @@ public final class UrlAuthorizationConfigurer> public final class StandardInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - /** - * @param context - */ private StandardInterceptUrlRegistry(ApplicationContext context) { setApplicationContext(context); } @@ -337,7 +334,7 @@ public final class UrlAuthorizationConfigurer> */ public StandardInterceptUrlRegistry access(String... attributes) { addMapping(this.requestMatchers, SecurityConfig.createList(attributes)); - return UrlAuthorizationConfigurer.this.REGISTRY; + return UrlAuthorizationConfigurer.this.registry; } protected List getMatchers() { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java index 7e8c85bfcc..93e1b09250 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java @@ -171,12 +171,8 @@ public final class X509Configurer> public void init(H http) { PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http)); - - // @formatter:off - http - .authenticationProvider(authenticationProvider) - .setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint()); - // @formatter:on + http.authenticationProvider(authenticationProvider).setSharedObject(AuthenticationEntryPoint.class, + new Http403ForbiddenEntryPoint()); } @Override diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java index 1c66412689..a8447e7d14 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java @@ -197,7 +197,6 @@ public final class OAuth2ClientConfigurer> */ public AuthorizationCodeGrantConfigurer authorizationRequestRepository( AuthorizationRequestRepository authorizationRequestRepository) { - Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; return this; @@ -212,7 +211,6 @@ public final class OAuth2ClientConfigurer> */ public AuthorizationCodeGrantConfigurer accessTokenResponseClient( OAuth2AccessTokenResponseClient accessTokenResponseClient) { - Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; return this; @@ -245,7 +243,6 @@ public final class OAuth2ClientConfigurer> OAuth2AuthorizationRequestResolver resolver = getAuthorizationRequestResolver(); OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = new OAuth2AuthorizationRequestRedirectFilter( resolver); - if (this.authorizationRequestRepository != null) { authorizationRequestRedirectFilter .setAuthorizationRequestRepository(this.authorizationRequestRepository); @@ -272,7 +269,6 @@ public final class OAuth2ClientConfigurer> OAuth2AuthorizationCodeGrantFilter authorizationCodeGrantFilter = new OAuth2AuthorizationCodeGrantFilter( OAuth2ClientConfigurerUtils.getClientRegistrationRepository(builder), OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(builder), authenticationManager); - if (this.authorizationRequestRepository != null) { authorizationCodeGrantFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java index bab025eff0..a7e0cc46cb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java @@ -291,7 +291,6 @@ public final class OAuth2LoginConfigurer> OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(this.getBuilder()), this.loginProcessingUrl); this.setAuthenticationFilter(authenticationFilter); super.loginProcessingUrl(this.loginProcessingUrl); - if (this.loginPage != null) { // Set custom login page super.loginPage(this.loginPage); @@ -311,12 +310,10 @@ public final class OAuth2LoginConfigurer> super.init(http); } } - OAuth2AccessTokenResponseClient accessTokenResponseClient = this.tokenEndpointConfig.accessTokenResponseClient; if (accessTokenResponseClient == null) { accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); } - OAuth2UserService oauth2UserService = getOAuth2UserService(); OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider = new OAuth2LoginAuthenticationProvider( accessTokenResponseClient, oauth2UserService); @@ -325,10 +322,8 @@ public final class OAuth2LoginConfigurer> oauth2LoginAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper); } http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider)); - boolean oidcAuthenticationProviderEnabled = ClassUtils .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); - if (oidcAuthenticationProviderEnabled) { OAuth2UserService oidcUserService = getOidcUserService(); OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider( @@ -345,14 +340,12 @@ public final class OAuth2LoginConfigurer> else { http.authenticationProvider(new OidcAuthenticationRequestChecker()); } - this.initDefaultLoginFilter(http); } @Override public void configure(B http) throws Exception { OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter; - if (this.authorizationEndpointConfig.authorizationRequestResolver != null) { authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter( this.authorizationEndpointConfig.authorizationRequestResolver); @@ -366,7 +359,6 @@ public final class OAuth2LoginConfigurer> OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), authorizationRequestBaseUri); } - if (this.authorizationEndpointConfig.authorizationRequestRepository != null) { authorizationRequestFilter .setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository); @@ -376,7 +368,6 @@ public final class OAuth2LoginConfigurer> authorizationRequestFilter.setRequestCache(requestCache); } http.addFilter(this.postProcess(authorizationRequestFilter)); - OAuth2LoginAuthenticationFilter authenticationFilter = this.getAuthenticationFilter(); if (this.redirectionEndpointConfig.authorizationResponseBaseUri != null) { authenticationFilter.setFilterProcessesUrl(this.redirectionEndpointConfig.authorizationResponseBaseUri); @@ -433,11 +424,7 @@ public final class OAuth2LoginConfigurer> ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OidcUserRequest.class, OidcUser.class); OAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - return new OidcUserService(); - } - - return bean; + return (bean != null) ? bean : new OidcUserService(); } private OAuth2UserService getOAuth2UserService() { @@ -447,29 +434,25 @@ public final class OAuth2LoginConfigurer> ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class, OAuth2User.class); OAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) { - List> userServices = new ArrayList<>(); - userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes)); - userServices.add(new DefaultOAuth2UserService()); - return new DelegatingOAuth2UserService<>(userServices); - } - else { - return new DefaultOAuth2UserService(); - } + if (bean != null) { + return bean; } - - return bean; + if (this.userInfoEndpointConfig.customUserTypes.isEmpty()) { + return new DefaultOAuth2UserService(); + } + List> userServices = new ArrayList<>(); + userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes)); + userServices.add(new DefaultOAuth2UserService()); + return new DelegatingOAuth2UserService<>(userServices); } private T getBeanOrNull(ResolvableType type) { ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class); - if (context == null) { - return null; - } - String[] names = context.getBeanNamesForType(type); - if (names.length == 1) { - return (T) context.getBean(names[0]); + if (context != null) { + String[] names = context.getBeanNamesForType(type); + if (names.length == 1) { + return (T) context.getBean(names[0]); + } } return null; } @@ -480,7 +463,6 @@ public final class OAuth2LoginConfigurer> if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) { return; } - loginPageGeneratingFilter.setOauth2LoginEnabled(true); loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(this.getLoginLinks()); loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage()); @@ -499,14 +481,12 @@ public final class OAuth2LoginConfigurer> if (clientRegistrations == null) { return Collections.emptyMap(); } - String authorizationRequestBaseUri = (this.authorizationEndpointConfig.authorizationRequestBaseUri != null) ? this.authorizationEndpointConfig.authorizationRequestBaseUri : OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; Map loginUrlToClientName = new HashMap<>(); clientRegistrations.forEach((registration) -> loginUrlToClientName.put( authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName())); - return loginUrlToClientName; } @@ -516,17 +496,13 @@ public final class OAuth2LoginConfigurer> RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http); RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher( new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); - RequestMatcher notXRequestedWith = new NegatedRequestMatcher( new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); - LinkedHashMap entryPoints = new LinkedHashMap<>(); entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)), new LoginUrlAuthenticationEntryPoint(providerLoginPage)); - DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint()); - return loginEntryPoint; } @@ -612,7 +588,6 @@ public final class OAuth2LoginConfigurer> */ public TokenEndpointConfig accessTokenResponseClient( OAuth2AccessTokenResponseClient accessTokenResponseClient) { - Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; return this; @@ -746,21 +721,19 @@ public final class OAuth2LoginConfigurer> @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication; - - // Section 3.1.2.1 Authentication Request - - // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest - // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() - .contains(OidcScopes.OPENID)) { - + OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationRequest(); + if (authorizationRequest.getScopes().contains(OidcScopes.OPENID)) { + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest scope + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope + // value. OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured", "An OpenID Connect Authentication Provider has not been configured. " + "Check to ensure you include the dependency 'spring-security-oauth2-jose'.", null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } - return null; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index 03053952f3..d56ca5bb4c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -180,7 +180,6 @@ public final class OAuth2ResourceServerConfigurer authenticationManager; } - BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver); filter.setBearerTokenResolver(bearerTokenResolver); filter.setAuthenticationEntryPoint(this.authenticationEntryPoint); filter = postProcess(filter); - http.addFilter(filter); } private void validateConfiguration() { if (this.authenticationManagerResolver == null) { - if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null) { - throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " - + "in Spring Security and neither was found. Make sure to configure JWT " - + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " - + "http.oauth2ResourceServer().opaqueToken()."); - } - - if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) { - throw new IllegalStateException( - "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); - } + Assert.state(this.jwtConfigurer != null || this.opaqueTokenConfigurer != null, + "Jwt and Opaque Token are the only supported formats for bearer tokens " + + "in Spring Security and neither was found. Make sure to configure JWT " + + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " + + "http.oauth2ResourceServer().opaqueToken()."); + Assert.state(this.jwtConfigurer == null || this.opaqueTokenConfigurer == null, + "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); } else { - if (this.jwtConfigurer != null || this.opaqueTokenConfigurer != null) { - throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " - + "precedence over any jwt() or opaqueToken() configuration."); - } + Assert.state(this.jwtConfigurer == null && this.opaqueTokenConfigurer == null, + "If an authenticationManagerResolver() is configured, then it takes " + + "precedence over any jwt() or opaqueToken() configuration."); } } private void registerDefaultAccessDeniedHandler(H http) { ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if (exceptionHandling == null) { - return; + if (exceptionHandling != null) { + exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher); } - - exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher); } private void registerDefaultEntryPoint(H http) { ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if (exceptionHandling == null) { - return; + if (exceptionHandling != null) { + exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher); } - - exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher); } private void registerDefaultCsrfOverride(H http) { CsrfConfigurer csrf = http.getConfigurer(CsrfConfigurer.class); - if (csrf == null) { - return; + if (csrf != null) { + csrf.ignoringRequestMatchers(this.requestMatcher); } - - csrf.ignoringRequestMatchers(this.requestMatcher); } AuthenticationProvider getAuthenticationProvider() { if (this.jwtConfigurer != null) { return this.jwtConfigurer.getAuthenticationProvider(); } - if (this.opaqueTokenConfigurer != null) { return this.opaqueTokenConfigurer.getAuthenticationProvider(); } - return null; } @@ -318,11 +298,9 @@ public final class OAuth2ResourceServerConfigurer jwtAuthenticationConverter) { - this.jwtAuthenticationConverter = jwtAuthenticationConverter; return this; } @@ -389,7 +365,6 @@ public final class OAuth2ResourceServerConfigurer jwtAuthenticationConverter = getJwtAuthenticationConverter(); - JwtAuthenticationProvider provider = new JwtAuthenticationProvider(decoder); provider.setJwtAuthenticationConverter(jwtAuthenticationConverter); return postProcess(provider); @@ -418,7 +390,6 @@ public final class OAuth2ResourceServerConfigurer> @Override public void init(H http) throws Exception { super.init(http); - OpenIDAuthenticationProvider authenticationProvider = new OpenIDAuthenticationProvider(); authenticationProvider.setAuthenticationUserDetailsService(getAuthenticationUserDetailsService(http)); authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); - initDefaultLoginFilter(http); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java index e73183dc28..4adad193d6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java @@ -160,9 +160,6 @@ public final class Saml2LoginConfigurer> return this; } - /** - * {@inheritDoc} - */ @Override public Saml2LoginConfigurer loginPage(String loginPage) { Assert.hasText(loginPage, "loginPage cannot be empty"); @@ -170,9 +167,6 @@ public final class Saml2LoginConfigurer> return this; } - /** - * {@inheritDoc} - */ @Override public Saml2LoginConfigurer loginProcessingUrl(String loginProcessingUrl) { Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be empty"); @@ -181,9 +175,6 @@ public final class Saml2LoginConfigurer> return this; } - /** - * {@inheritDoc} - */ @Override protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) { return new AntPathRequestMatcher(loginProcessingUrl); @@ -208,28 +199,24 @@ public final class Saml2LoginConfigurer> if (this.relyingPartyRegistrationRepository == null) { this.relyingPartyRegistrationRepository = getSharedOrBean(http, RelyingPartyRegistrationRepository.class); } - this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http), this.loginProcessingUrl); setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter); super.loginProcessingUrl(this.loginProcessingUrl); - if (StringUtils.hasText(this.loginPage)) { // Set custom login page super.loginPage(this.loginPage); super.init(http); } else { - final Map providerUrlMap = getIdentityProviderUrlMap( + Map providerUrlMap = getIdentityProviderUrlMap( this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository); - boolean singleProvider = providerUrlMap.size() == 1; if (singleProvider) { // Setup auto-redirect to provider login page // when only 1 IDP is configured this.updateAuthenticationDefaults(); this.updateAccessDefaults(http); - String loginUrl = providerUrlMap.entrySet().iterator().next().getKey(); final LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(loginUrl); registerAuthenticationEntryPoint(http, entryPoint); @@ -238,7 +225,6 @@ public final class Saml2LoginConfigurer> super.init(http); } } - this.initDefaultLoginFilter(http); } @@ -279,7 +265,6 @@ public final class Saml2LoginConfigurer> if (csrf == null) { return; } - csrf.ignoringRequestMatchers(new AntPathRequestMatcher(this.loginProcessingUrl)); } @@ -289,7 +274,6 @@ public final class Saml2LoginConfigurer> if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) { return; } - loginPageGeneratingFilter.setSaml2LoginEnabled(true); loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName(this.getIdentityProviderUrlMap( this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository)); @@ -326,8 +310,8 @@ public final class Saml2LoginConfigurer> return context.getBean(clazz); } catch (NoSuchBeanDefinitionException ex) { + return null; } - return null; } private void setSharedObject(B http, Class clazz, C object) { @@ -346,7 +330,6 @@ public final class Saml2LoginConfigurer> private Filter build(B http) { Saml2AuthenticationRequestFactory authenticationRequestResolver = getResolver(http); Saml2AuthenticationRequestContextResolver contextResolver = getContextResolver(http); - return postProcess( new Saml2WebSsoAuthenticationRequestFilter(contextResolver, authenticationRequestResolver)); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java index 52257b6c2d..eee7e34f36 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java @@ -442,11 +442,11 @@ public class MessageSecurityMetadataSourceRegistry { return new SimpDestinationMessageMatcher(this.pattern, MessageSecurityMetadataSourceRegistry.this.pathMatcher); } - else if (SimpMessageType.MESSAGE == this.type) { + if (SimpMessageType.MESSAGE == this.type) { return SimpDestinationMessageMatcher.createMessageMatcher(this.pattern, MessageSecurityMetadataSourceRegistry.this.pathMatcher); } - else if (SimpMessageType.SUBSCRIBE == this.type) { + if (SimpMessageType.SUBSCRIBE == this.type) { return SimpDestinationMessageMatcher.createSubscribeMatcher(this.pattern, MessageSecurityMetadataSourceRegistry.this.pathMatcher); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java index 46b109fc28..5a56f25650 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java @@ -47,13 +47,12 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean oauth2ClientPresent = ClassUtils.isPresent( - "org.springframework.security.oauth2.client.registration.ClientRegistration", - getClass().getClassLoader()); - - return oauth2ClientPresent ? new String[] { - "org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" } - : new String[] {}; + if (!ClassUtils.isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration", + getClass().getClassLoader())) { + return new String[0]; + } + return new String[] { "org.springframework.security.config.annotation.web.reactive." + + "ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" }; } @Configuration(proxyBeanMethods = false) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java index de54752001..07119e8ee0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java @@ -98,23 +98,14 @@ class WebFluxSecurityConfiguration { * @return */ private SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - // @formatter:off - http - .authorizeExchange() - .anyExchange().authenticated(); - // @formatter:on - + http.authorizeExchange().anyExchange().authenticated(); if (isOAuth2Present && OAuth2ClasspathGuard.shouldConfigure(this.context)) { OAuth2ClasspathGuard.configure(this.context, http); } else { - // @formatter:off - http - .httpBasic().and() - .formLogin(); - // @formatter:on + http.httpBasic(); + http.formLogin(); } - SecurityWebFilterChain result = http.build(); return result; } @@ -122,11 +113,8 @@ class WebFluxSecurityConfiguration { private static class OAuth2ClasspathGuard { static void configure(ApplicationContext context, ServerHttpSecurity http) { - // @formatter:off - http - .oauth2Login().and() - .oauth2Client(); - // @formatter:on + http.oauth2Login(); + http.oauth2Client(); } static boolean shouldConfigure(ApplicationContext context) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java index bd95622830..f201352f59 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java @@ -47,6 +47,7 @@ import org.springframework.security.messaging.context.SecurityContextChannelInte import org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor; import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor; import org.springframework.util.AntPathMatcher; +import org.springframework.util.Assert; import org.springframework.util.PathMatcher; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; @@ -160,10 +161,8 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A messageSecurityMetadataSource); MessageExpressionVoter voter = new MessageExpressionVoter<>(); voter.setExpressionHandler(getMessageExpressionHandler()); - List> voters = new ArrayList<>(); voters.add(voter); - AffirmativeBased manager = new AffirmativeBased(voters); channelSecurityInterceptor.setAccessDecisionManager(manager); return channelSecurityInterceptor; @@ -221,50 +220,47 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A if (sameOriginDisabled()) { return; } - String beanName = "stompWebSocketHandlerMapping"; SimpleUrlHandlerMapping mapping = this.context.getBean(beanName, SimpleUrlHandlerMapping.class); Map mappings = mapping.getHandlerMap(); for (Object object : mappings.values()) { if (object instanceof SockJsHttpRequestHandler) { - SockJsHttpRequestHandler sockjsHandler = (SockJsHttpRequestHandler) object; - SockJsService sockJsService = sockjsHandler.getSockJsService(); - if (!(sockJsService instanceof TransportHandlingSockJsService)) { - throw new IllegalStateException( - "sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService); - } - - TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService; - List handshakeInterceptors = transportHandlingSockJsService - .getHandshakeInterceptors(); - List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); - interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); - interceptorsToSet.addAll(handshakeInterceptors); - - transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet); + setHandshakeInterceptors((SockJsHttpRequestHandler) object); } else if (object instanceof WebSocketHttpRequestHandler) { - WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) object; - List handshakeInterceptors = handler.getHandshakeInterceptors(); - List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); - interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); - interceptorsToSet.addAll(handshakeInterceptors); - - handler.setHandshakeInterceptors(interceptorsToSet); + setHandshakeInterceptors((WebSocketHttpRequestHandler) object); } else { - throw new IllegalStateException("Bean " + beanName - + " is expected to contain mappings to either a SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " - + object); + throw new IllegalStateException("Bean " + beanName + " is expected to contain mappings to either a " + + "SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " + object); } } - if (this.inboundRegistry.containsMapping() && !this.inboundRegistry.isSimpDestPathMatcherConfigured()) { PathMatcher pathMatcher = getDefaultPathMatcher(); this.inboundRegistry.simpDestPathMatcher(pathMatcher); } } + private void setHandshakeInterceptors(SockJsHttpRequestHandler handler) { + SockJsService sockJsService = handler.getSockJsService(); + Assert.state(sockJsService instanceof TransportHandlingSockJsService, + () -> "sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService); + TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService; + List handshakeInterceptors = transportHandlingSockJsService.getHandshakeInterceptors(); + List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); + interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); + interceptorsToSet.addAll(handshakeInterceptors); + transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet); + } + + private void setHandshakeInterceptors(WebSocketHttpRequestHandler handler) { + List handshakeInterceptors = handler.getHandshakeInterceptors(); + List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); + interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); + interceptorsToSet.addAll(handshakeInterceptors); + handler.setHandshakeInterceptors(interceptorsToSet); + } + private static class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry { @Override diff --git a/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java index efce360644..883e98bc39 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java @@ -47,36 +47,27 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements @Override public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClassName(element)); - doParse(element, parserContext, builder); - RootBeanDefinition userService = (RootBeanDefinition) builder.getBeanDefinition(); - final String beanId = resolveId(element, userService, parserContext); - + String beanId = resolveId(element, userService, parserContext); parserContext.registerBeanComponent(new BeanComponentDefinition(userService, beanId)); - String cacheRef = element.getAttribute(CACHE_REF); - // Register a caching version of the user service if there's a cache-ref if (StringUtils.hasText(cacheRef)) { BeanDefinitionBuilder cachingUSBuilder = BeanDefinitionBuilder .rootBeanDefinition(CachingUserDetailsService.class); cachingUSBuilder.addConstructorArgReference(beanId); - cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference(cacheRef)); BeanDefinition cachingUserService = cachingUSBuilder.getBeanDefinition(); parserContext .registerBeanComponent(new BeanComponentDefinition(cachingUserService, beanId + CACHING_SUFFIX)); } - return null; } private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext pc) throws BeanDefinitionStoreException { - String id = element.getAttribute("id"); - if (pc.isNested()) { // We're inside an element if (!StringUtils.hasText(id)) { @@ -85,17 +76,14 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements BeanDefinition container = pc.getContainingBeanDefinition(); container.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(id)); } - if (StringUtils.hasText(id)) { return id; } - // If top level, use the default name or throw an exception if already used if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) { throw new BeanDefinitionStoreException( - "No id supplied and another " + "bean is already registered as " + BeanIds.USER_DETAILS_SERVICE); + "No id supplied and another bean is already registered as " + BeanIds.USER_DETAILS_SERVICE); } - return BeanIds.USER_DETAILS_SERVICE; } diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java index acdba6c0c9..0439549e28 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java @@ -60,7 +60,6 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition @Override public BeanDefinition parse(Element element, ParserContext pc) { String id = element.getAttribute("id"); - if (!StringUtils.hasText(id)) { if (pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) { pc.getReaderContext().warning("Overriding globally registered AuthenticationManager", @@ -69,65 +68,30 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition id = BeanIds.AUTHENTICATION_MANAGER; } pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element))); - BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class); - String alias = element.getAttribute(ATT_ALIAS); - List providers = new ManagedList<>(); NamespaceHandlerResolver resolver = pc.getReaderContext().getNamespaceHandlerResolver(); - NodeList children = element.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node instanceof Element) { - Element providerElt = (Element) node; - if (StringUtils.hasText(providerElt.getAttribute(ATT_REF))) { - if (providerElt.getAttributes().getLength() > 1) { - pc.getReaderContext() - .error("authentication-provider element cannot be used with other attributes " - + "when using 'ref' attribute", pc.extractSource(element)); - } - NodeList providerChildren = providerElt.getChildNodes(); - for (int j = 0; j < providerChildren.getLength(); j++) { - if (providerChildren.item(j) instanceof Element) { - pc.getReaderContext() - .error("authentication-provider element cannot have child elements when used " - + "with 'ref' attribute", pc.extractSource(element)); - } - } - providers.add(new RuntimeBeanReference(providerElt.getAttribute(ATT_REF))); - } - else { - BeanDefinition provider = resolver.resolve(providerElt.getNamespaceURI()).parse(providerElt, pc); - Assert.notNull(provider, - () -> "Parser for " + providerElt.getNodeName() + " returned a null bean definition"); - String providerId = pc.getReaderContext().generateBeanName(provider); - pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId)); - providers.add(new RuntimeBeanReference(providerId)); - } + providers.add(extracted(element, pc, resolver, (Element) node)); } } - if (providers.isEmpty()) { providers.add(new RootBeanDefinition(NullAuthenticationProvider.class)); } - providerManagerBldr.addConstructorArgValue(providers); - if ("false".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) { providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", false); } - // Add the default event publisher BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class); String pubId = pc.getReaderContext().generateBeanName(publisher); pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId)); providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId); - pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), id)); - if (StringUtils.hasText(alias)) { pc.getRegistry().registerAlias(id, alias); pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element)); @@ -136,12 +100,35 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition pc.getRegistry().registerAlias(id, BeanIds.AUTHENTICATION_MANAGER); pc.getReaderContext().fireAliasRegistered(id, BeanIds.AUTHENTICATION_MANAGER, pc.extractSource(element)); } - pc.popAndRegisterContainingComponent(); - return null; } + private BeanMetadataElement extracted(Element element, ParserContext pc, NamespaceHandlerResolver resolver, + Element providerElement) { + String ref = providerElement.getAttribute(ATT_REF); + if (!StringUtils.hasText(ref)) { + BeanDefinition provider = resolver.resolve(providerElement.getNamespaceURI()).parse(providerElement, pc); + Assert.notNull(provider, + () -> "Parser for " + providerElement.getNodeName() + " returned a null bean definition"); + String providerId = pc.getReaderContext().generateBeanName(provider); + pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId)); + return new RuntimeBeanReference(providerId); + } + if (providerElement.getAttributes().getLength() > 1) { + pc.getReaderContext().error("authentication-provider element cannot be used with other attributes " + + "when using 'ref' attribute", pc.extractSource(element)); + } + NodeList providerChildren = providerElement.getChildNodes(); + for (int i = 0; i < providerChildren.getLength(); i++) { + if (providerChildren.item(i) instanceof Element) { + pc.getReaderContext().error("authentication-provider element cannot have child elements when used " + + "with 'ref' attribute", pc.extractSource(element)); + } + } + return new RuntimeBeanReference(ref); + } + /** * Provider which doesn't provide any service. Only used to prevent a configuration * exception if the provider list is empty (usually because a child ProviderManager diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java index 096d1dad4c..ce199e8ea3 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java @@ -56,12 +56,10 @@ public class AuthenticationManagerFactoryBean implements FactoryBean> ENCODER_CLASSES; - - static { - ENCODER_CLASSES = new HashMap<>(); - ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class); - } - - private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class); + private static final Map> ENCODER_CLASSES = Collections.singletonMap(OPT_HASH_BCRYPT, + BCryptPasswordEncoder.class); private BeanMetadataElement passwordEncoder; @@ -68,14 +62,9 @@ public class PasswordEncoderParser { return; } String hash = element.getAttribute(ATT_HASH); - boolean useBase64 = false; - - if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) { - useBase64 = Boolean.parseBoolean(element.getAttribute(ATT_BASE_64)); - } - + boolean useBase64 = StringUtils.hasText(element.getAttribute(ATT_BASE_64)) + && Boolean.parseBoolean(element.getAttribute(ATT_BASE_64)); String ref = element.getAttribute(ATT_REF); - if (StringUtils.hasText(ref)) { this.passwordEncoder = new RuntimeBeanReference(ref); } diff --git a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java index 882a67fbde..eecd64bf28 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java @@ -62,43 +62,33 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String userProperties = element.getAttribute(ATT_PROPERTIES); List userElts = DomUtils.getChildElementsByTagName(element, ELT_USER); - if (StringUtils.hasText(userProperties)) { - if (!CollectionUtils.isEmpty(userElts)) { throw new BeanDefinitionStoreException( "Use of a properties file and user elements are mutually exclusive"); } - BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class); bd.getPropertyValues().addPropertyValue("location", userProperties); builder.addConstructorArgValue(bd); - return; } - if (CollectionUtils.isEmpty(userElts)) { throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER + "> child elements or a " + "properties file (using the '" + ATT_PROPERTIES + "' attribute)"); } - ManagedList users = new ManagedList<>(); - for (Object elt : userElts) { Element userElt = (Element) elt; String userName = userElt.getAttribute(ATT_NAME); String password = userElt.getAttribute(ATT_PASSWORD); - if (!StringUtils.hasLength(password)) { password = generateRandomPassword(); } - boolean locked = "true".equals(userElt.getAttribute(ATT_LOCKED)); boolean disabled = "true".equals(userElt.getAttribute(ATT_DISABLED)); BeanDefinitionBuilder authorities = BeanDefinitionBuilder.rootBeanDefinition(AuthorityUtils.class); authorities.addConstructorArgValue(userElt.getAttribute(ATT_AUTHORITIES)); authorities.setFactoryMethod("commaSeparatedStringToAuthorityList"); - BeanDefinitionBuilder user = BeanDefinitionBuilder.rootBeanDefinition(User.class); user.addConstructorArgValue(userName); user.addConstructorArgValue(password); @@ -107,10 +97,8 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB user.addConstructorArgValue(true); user.addConstructorArgValue(!locked); user.addConstructorArgValue(authorities.getBeanDefinition()); - users.add(user.getBeanDefinition()); } - builder.addConstructorArgValue(users); } diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java index e01f3daff9..7b36a5ee19 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java @@ -18,9 +18,11 @@ package org.springframework.security.config.core.userdetails; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import org.springframework.beans.factory.FactoryBean; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.memory.UserAttribute; @@ -58,27 +60,19 @@ public class UserDetailsMapFactoryBean implements FactoryBean getObject() { Collection users = new ArrayList<>(this.userProperties.size()); - UserAttributeEditor editor = new UserAttributeEditor(); - for (Map.Entry entry : this.userProperties.entrySet()) { - String name = entry.getKey(); - String property = entry.getValue(); + this.userProperties.forEach((name, property) -> { editor.setAsText(property); UserAttribute attr = (UserAttribute) editor.getValue(); - if (attr == null) { - throw new IllegalStateException("The entry with username '" + name + "' and value '" + property - + "' could not be converted to a UserDetails."); - } - // @formatter:off - UserDetails user = User.withUsername(name) - .password(attr.getPassword()) - .disabled(!attr.isEnabled()) - .authorities(attr.getAuthorities()) - .build(); - users.add(user); - // @formatter:on - } + Assert.state(attr != null, () -> "The entry with username '" + name + "' and value '" + property + + "' could not be converted to a UserDetails."); + String password = attr.getPassword(); + boolean disabled = !attr.isEnabled(); + List authorities = attr.getAuthorities(); + users.add(User.withUsername(name).password(password).disabled(disabled).authorities(authorities).build()); + }); return users; + } @Override diff --git a/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java b/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java index 6fbde50351..5174a62bc5 100644 --- a/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java @@ -57,18 +57,13 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc this.resourceLoader = resourceLoader; } - /** - * {@inheritDoc} - */ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (hasUserDefinedConversionService(beanFactory)) { return; } - Converter pkcs8 = pkcs8(); Converter x509 = x509(); - ConversionService service = beanFactory.getConversionService(); if (service instanceof ConverterRegistry) { ConverterRegistry registry = (ConverterRegistry) service; diff --git a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java index a587f84b89..d3c0ce32f4 100644 --- a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java @@ -86,12 +86,15 @@ final class AuthenticationConfigBuilder { private static final String DEF_REALM = "Realm"; static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter"; + static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider"; private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer"; + static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute"; private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory"; + static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"; static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref"; @@ -106,6 +109,8 @@ final class AuthenticationConfigBuilder { private static final String ATT_KEY = "key"; + private static final String ATT_MAPPABLE_ROLES = "mappable-roles"; + private final Element httpElt; private final ParserContext pc; @@ -226,7 +231,6 @@ final class AuthenticationConfigBuilder { this.portMapper = portMapper; this.portResolver = portResolver; this.csrfLogoutHandler = csrfLogoutHandler; - createAnonymousFilter(); createRememberMeFilter(authenticationManager); createBasicFilter(authenticationManager); @@ -243,18 +247,14 @@ final class AuthenticationConfigBuilder { } void createRememberMeFilter(BeanReference authenticationManager) { - // Parse remember me before logout as RememberMeServices is also a LogoutHandler // implementation. Element rememberMeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REMEMBER_ME); - if (rememberMeElt != null) { String key = rememberMeElt.getAttribute(ATT_KEY); - if (!StringUtils.hasText(key)) { key = createKey(); } - RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser(key, authenticationManager); this.rememberMeFilter = rememberMeParser.parse(rememberMeElt, this.pc); @@ -266,36 +266,28 @@ final class AuthenticationConfigBuilder { private void createRememberMeProvider(String key) { RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class); provider.setSource(this.rememberMeFilter.getSource()); - provider.getConstructorArgumentValues().addGenericArgumentValue(key); - String id = this.pc.getReaderContext().generateBeanName(provider); this.pc.registerBeanComponent(new BeanComponentDefinition(provider, id)); - this.rememberMeProviderRef = new RuntimeBeanReference(id); } void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) { - Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN); RootBeanDefinition formFilter = null; - if (formLoginElt != null || this.autoConfig) { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login", "POST", AUTHENTICATION_PROCESSING_FILTER_CLASS, this.requestCache, sessionStrategy, this.allowSessionCreation, this.portMapper, this.portResolver); - parser.parse(formLoginElt, this.pc); formFilter = parser.getFilterBean(); this.formEntryPoint = parser.getEntryPointBean(); this.loginProcessingUrl = parser.getLoginProcessingUrl(); this.formLoginPage = parser.getLoginPage(); } - if (formFilter != null) { formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation); formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager); - // Id is required by login page filter this.formFilterId = this.pc.getReaderContext().generateBeanName(formFilter); this.pc.registerBeanComponent(new BeanComponentDefinition(formFilter, this.formFilterId)); @@ -316,14 +308,11 @@ final class AuthenticationConfigBuilder { return; } this.oauth2LoginEnabled = true; - OAuth2LoginBeanDefinitionParser parser = new OAuth2LoginBeanDefinitionParser(this.requestCache, this.portMapper, this.portResolver, sessionStrategy, this.allowSessionCreation); BeanDefinition oauth2LoginFilterBean = parser.parse(oauth2LoginElt, this.pc); - BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository(); registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository); - oauth2LoginFilterBean.getPropertyValues().addPropertyValue("authenticationManager", authManager); // retrieve the other bean result @@ -360,26 +349,21 @@ final class AuthenticationConfigBuilder { return; } this.oauth2ClientEnabled = true; - OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache, authenticationManager); parser.parse(oauth2ClientElt, this.pc); - BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository(); registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository); - this.authorizationRequestRedirectFilter = parser.getAuthorizationRequestRedirectFilter(); String authorizationRequestRedirectFilterId = this.pc.getReaderContext() .generateBeanName(this.authorizationRequestRedirectFilter); this.pc.registerBeanComponent(new BeanComponentDefinition(this.authorizationRequestRedirectFilter, authorizationRequestRedirectFilterId)); - this.authorizationCodeGrantFilter = parser.getAuthorizationCodeGrantFilter(); String authorizationCodeGrantFilterId = this.pc.getReaderContext() .generateBeanName(this.authorizationCodeGrantFilter); this.pc.registerBeanComponent( new BeanComponentDefinition(this.authorizationCodeGrantFilter, authorizationCodeGrantFilterId)); - BeanDefinition authorizationCodeAuthenticationProvider = parser.getAuthorizationCodeAuthenticationProvider(); String authorizationCodeAuthenticationProviderId = this.pc.getReaderContext() .generateBeanName(authorizationCodeAuthenticationProvider); @@ -403,7 +387,6 @@ final class AuthenticationConfigBuilder { if (!this.oauth2LoginEnabled && !this.oauth2ClientEnabled) { return; } - boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader()); if (webmvcPresent) { @@ -415,11 +398,9 @@ final class AuthenticationConfigBuilder { void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) { Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN); RootBeanDefinition openIDFilter = null; - if (openIDLoginElt != null) { openIDFilter = parseOpenIDFilter(sessionStrategy, openIDLoginElt); } - if (openIDFilter != null) { openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation); openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager); @@ -427,7 +408,6 @@ final class AuthenticationConfigBuilder { this.openIDFilterId = this.pc.getReaderContext().generateBeanName(openIDFilter); this.pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, this.openIDFilterId)); injectRememberMeServicesRef(openIDFilter, this.rememberMeServicesId); - createOpenIDProvider(); } } @@ -454,19 +434,15 @@ final class AuthenticationConfigBuilder { this.openIDEntryPoint = parser.getEntryPointBean(); this.openidLoginProcessingUrl = parser.getLoginProcessingUrl(); this.openIDLoginPage = parser.getLoginPage(); - List attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE); - if (!attrExElts.isEmpty()) { // Set up the consumer with the required attribute list BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS); BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS); ManagedMap> axMap = new ManagedMap<>(); - for (Element attrExElt : attrExElts) { String identifierMatch = attrExElt.getAttribute("identifier-match"); - if (!StringUtils.hasText(identifierMatch)) { if (attrExElts.size() > 1) { this.pc.getReaderContext().error("You must supply an identifier-match attribute if using more" @@ -475,11 +451,9 @@ final class AuthenticationConfigBuilder { // Match anything identifierMatch = ".*"; } - axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt)); } axFactory.addConstructorArgValue(axMap); - consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition()); openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition()); } @@ -499,13 +473,11 @@ final class AuthenticationConfigBuilder { if (StringUtils.hasLength(required)) { attrBldr.addPropertyValue("required", Boolean.valueOf(required)); } - if (StringUtils.hasLength(count)) { attrBldr.addPropertyValue("count", Integer.parseInt(count)); } attributes.add(attrBldr.getBeanDefinition()); } - return attributes; } @@ -513,14 +485,11 @@ final class AuthenticationConfigBuilder { Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN); BeanDefinitionBuilder openIDProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS); - RootBeanDefinition uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("authenticationUserDetailsService"); uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF)); - openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds); - BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition(); this.openIDProviderRef = new RuntimeBeanReference( this.pc.getReaderContext().registerWithGeneratedName(openIDProvider)); @@ -535,30 +504,22 @@ final class AuthenticationConfigBuilder { void createBasicFilter(BeanReference authManager) { Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH); - if (basicAuthElt == null && !this.autoConfig) { // No basic auth, do nothing return; } - String realm = this.httpElt.getAttribute(ATT_REALM); if (!StringUtils.hasText(realm)) { realm = DEF_REALM; } - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class); - String entryPointId; - if (basicAuthElt != null) { if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) { this.basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF)); } - injectAuthenticationDetailsSource(basicAuthElt, filterBuilder); - } - if (this.basicEntryPoint == null) { RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class); entryPoint.setSource(this.pc.extractSource(this.httpElt)); @@ -567,7 +528,6 @@ final class AuthenticationConfigBuilder { this.pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId)); this.basicEntryPoint = new RuntimeBeanReference(entryPointId); } - filterBuilder.addConstructorArgValue(authManager); filterBuilder.addConstructorArgValue(this.basicEntryPoint); this.basicFilter = filterBuilder.getBeanDefinition(); @@ -575,12 +535,10 @@ final class AuthenticationConfigBuilder { void createBearerTokenAuthenticationFilter(BeanReference authManager) { Element resourceServerElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_RESOURCE_SERVER); - if (resourceServerElt == null) { // No resource server, do nothing return; } - OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = new OAuth2ResourceServerBeanDefinitionParser( authManager, this.authenticationProviders, this.defaultEntryPointMappings, this.defaultDeniedHandlerMappings, this.csrfIgnoreRequestMatchers); @@ -590,37 +548,28 @@ final class AuthenticationConfigBuilder { void createX509Filter(BeanReference authManager) { Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509); RootBeanDefinition filter = null; - if (x509Elt != null) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder .rootBeanDefinition(X509AuthenticationFilter.class); filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(x509Elt)); filterBuilder.addPropertyValue("authenticationManager", authManager); - String regex = x509Elt.getAttribute("subject-principal-regex"); - if (StringUtils.hasText(regex)) { BeanDefinitionBuilder extractor = BeanDefinitionBuilder .rootBeanDefinition(SubjectDnX509PrincipalExtractor.class); extractor.addPropertyValue("subjectDnRegex", regex); - filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition()); } - injectAuthenticationDetailsSource(x509Elt, filterBuilder); - filter = (RootBeanDefinition) filterBuilder.getBeanDefinition(); createPrauthEntryPoint(x509Elt); - createX509Provider(); } - this.x509Filter = filter; } private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) { String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF); - if (StringUtils.hasText(authDetailsSourceRef)) { filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef); } @@ -629,14 +578,11 @@ final class AuthenticationConfigBuilder { private void createX509Provider() { Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509); BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class); - RootBeanDefinition uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("authenticationUserDetailsService"); uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF)); - provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds); - this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider)); } @@ -648,47 +594,37 @@ final class AuthenticationConfigBuilder { } void createJeeFilter(BeanReference authManager) { - final String ATT_MAPPABLE_ROLES = "mappable-roles"; - Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE); RootBeanDefinition filter = null; - if (jeeElt != null) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder .rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class); filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(jeeElt)); filterBuilder.addPropertyValue("authenticationManager", authManager); - BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder .rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class); adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper", new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class)); - String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES); Assert.hasLength(roles, "roles is expected to have length"); BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class); rolesBuilder.addConstructorArgValue(roles); rolesBuilder.setFactoryMethod("commaDelimitedListToSet"); - RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class); mappableRolesRetriever.getPropertyValues().addPropertyValue("mappableAttributes", rolesBuilder.getBeanDefinition()); adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever); filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition()); - filter = (RootBeanDefinition) filterBuilder.getBeanDefinition(); - createPrauthEntryPoint(jeeElt); createJeeProvider(); } - this.jeeFilter = filter; } private void createJeeProvider() { Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE); BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class); - RootBeanDefinition uds; if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) { uds = new RootBeanDefinition(); @@ -699,16 +635,13 @@ final class AuthenticationConfigBuilder { else { uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class); } - provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds); - this.jeeProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider)); } void createLoginPageFilterIfNeeded() { boolean needLoginPage = this.formFilterId != null || this.openIDFilterId != null || this.oauth2LoginFilterId != null; - // If no login page has been defined, add in the default page generator. if (needLoginPage && this.formLoginPage == null && this.openIDLoginPage == null) { this.logger.info("No login page configured. The default internal one will be used. Use the '" @@ -720,23 +653,19 @@ final class AuthenticationConfigBuilder { BeanDefinitionBuilder logoutPageFilter = BeanDefinitionBuilder .rootBeanDefinition(DefaultLogoutPageGeneratingFilter.class); logoutPageFilter.addPropertyValue("resolveHiddenInputs", new CsrfTokenHiddenInputFunction()); - if (this.formFilterId != null) { loginPageFilter.addConstructorArgReference(this.formFilterId); loginPageFilter.addPropertyValue("authenticationUrl", this.loginProcessingUrl); } - if (this.openIDFilterId != null) { loginPageFilter.addConstructorArgReference(this.openIDFilterId); loginPageFilter.addPropertyValue("openIDauthenticationUrl", this.openidLoginProcessingUrl); } - if (this.oauth2LoginFilterId != null) { loginPageFilter.addConstructorArgReference(this.oauth2LoginFilterId); loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true); loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks); } - this.loginPageGenerationFilter = loginPageFilter.getBeanDefinition(); this.logoutPageGenerationFilter = logoutPageFilter.getBeanDefinition(); } @@ -784,51 +713,41 @@ final class AuthenticationConfigBuilder { void createAnonymousFilter() { Element anonymousElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.ANONYMOUS); - if (anonymousElt != null && "false".equals(anonymousElt.getAttribute("enabled"))) { return; } - String grantedAuthority = null; String username = null; String key = null; Object source = this.pc.extractSource(this.httpElt); - if (anonymousElt != null) { grantedAuthority = anonymousElt.getAttribute("granted-authority"); username = anonymousElt.getAttribute("username"); key = anonymousElt.getAttribute(ATT_KEY); source = this.pc.extractSource(anonymousElt); } - if (!StringUtils.hasText(grantedAuthority)) { grantedAuthority = "ROLE_ANONYMOUS"; } - if (!StringUtils.hasText(username)) { username = "anonymousUser"; } - if (!StringUtils.hasText(key)) { // Generate a random key for the Anonymous provider key = createKey(); } - this.anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class); this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(0, key); this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username); this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2, AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority)); this.anonymousFilter.setSource(source); - RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class); anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, key); anonymousProviderBean.setSource(this.anonymousFilter.getSource()); String id = this.pc.getReaderContext().generateBeanName(anonymousProviderBean); this.pc.registerBeanComponent(new BeanComponentDefinition(anonymousProviderBean, id)); - this.anonymousProviderRef = new RuntimeBeanReference(id); - } private String createKey() { @@ -840,11 +759,10 @@ final class AuthenticationConfigBuilder { BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class); this.accessDeniedHandler = createAccessDeniedHandler(this.httpElt, this.pc); etfBuilder.addPropertyValue("accessDeniedHandler", this.accessDeniedHandler); - assert this.requestCache != null; + Assert.state(this.requestCache != null, "No request cache found"); this.mainEntryPoint = selectEntryPoint(); etfBuilder.addConstructorArgValue(this.mainEntryPoint); etfBuilder.addConstructorArgValue(this.requestCache); - this.etf = etfBuilder.getBeanDefinition(); } @@ -852,11 +770,9 @@ final class AuthenticationConfigBuilder { Element accessDeniedElt = DomUtils.getChildElementByTagName(element, Elements.ACCESS_DENIED_HANDLER); BeanDefinitionBuilder accessDeniedHandler = BeanDefinitionBuilder .rootBeanDefinition(AccessDeniedHandlerImpl.class); - if (accessDeniedElt != null) { String errorPage = accessDeniedElt.getAttribute("error-page"); String ref = accessDeniedElt.getAttribute("ref"); - if (StringUtils.hasText(errorPage)) { if (StringUtils.hasText(ref)) { pc.getReaderContext() @@ -868,25 +784,21 @@ final class AuthenticationConfigBuilder { accessDeniedHandler.addPropertyValue("errorPage", errorPage); return accessDeniedHandler.getBeanDefinition(); } - else if (StringUtils.hasText(ref)) { + if (StringUtils.hasText(ref)) { return new RuntimeBeanReference(ref); } - } - if (this.defaultDeniedHandlerMappings.isEmpty()) { return accessDeniedHandler.getBeanDefinition(); } if (this.defaultDeniedHandlerMappings.size() == 1) { return this.defaultDeniedHandlerMappings.values().iterator().next(); } - accessDeniedHandler = BeanDefinitionBuilder .rootBeanDefinition(RequestMatcherDelegatingAccessDeniedHandler.class); accessDeniedHandler.addConstructorArgValue(this.defaultDeniedHandlerMappings); accessDeniedHandler .addConstructorArgValue(BeanDefinitionBuilder.rootBeanDefinition(AccessDeniedHandlerImpl.class)); - return accessDeniedHandler.getBeanDefinition(); } @@ -894,11 +806,9 @@ final class AuthenticationConfigBuilder { // We need to establish the main entry point. // First check if a custom entry point bean is set String customEntryPoint = this.httpElt.getAttribute(ATT_ENTRY_POINT_REF); - if (StringUtils.hasText(customEntryPoint)) { return new RuntimeBeanReference(customEntryPoint); } - if (!this.defaultEntryPointMappings.isEmpty()) { if (this.defaultEntryPointMappings.size() == 1) { return this.defaultEntryPointMappings.values().iterator().next(); @@ -908,7 +818,6 @@ final class AuthenticationConfigBuilder { delegatingEntryPoint.addConstructorArgValue(this.defaultEntryPointMappings); return delegatingEntryPoint.getBeanDefinition(); } - Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH); Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN); Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN); @@ -917,21 +826,17 @@ final class AuthenticationConfigBuilder { && this.oauth2LoginEntryPoint == null) { return this.basicEntryPoint; } - // If formLogin has been enabled either through an element or auto-config, then it // is used if no openID login page // has been set. - if (this.formLoginPage != null && this.openIDLoginPage != null) { this.pc.getReaderContext().error( "Only one login-page can be defined, either for OpenID or form-login, " + "but not both.", this.pc.extractSource(openIDLoginElt)); } - if (this.formFilterId != null && this.openIDLoginPage == null) { - // gh-6802 // If form login was enabled through element and Oauth2 login was enabled from - // element then use form login + // element then use form login (gh-6802) if (formLoginElt != null && this.oauth2LoginEntryPoint != null) { return this.formEntryPoint; } @@ -941,22 +846,18 @@ final class AuthenticationConfigBuilder { return this.formEntryPoint; } } - // Otherwise use OpenID if enabled if (this.openIDFilterId != null) { return this.openIDEntryPoint; } - // If X.509 or JEE have been enabled, use the preauth entry point. if (this.preAuthEntryPoint != null) { return this.preAuthEntryPoint; } - // OAuth2 entry point will not be null if only 1 client registration if (this.oauth2LoginEntryPoint != null) { return this.oauth2LoginEntryPoint; } - this.pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " + "make sure you have a login mechanism configured through the namespace (such as form-login) or " + "specify a custom AuthenticationEntryPoint with the '" + ATT_ENTRY_POINT_REF + "' attribute ", @@ -976,107 +877,83 @@ final class AuthenticationConfigBuilder { List getFilters() { List filters = new ArrayList<>(); - if (this.anonymousFilter != null) { filters.add(new OrderDecorator(this.anonymousFilter, SecurityFilters.ANONYMOUS_FILTER)); } - if (this.rememberMeFilter != null) { filters.add(new OrderDecorator(this.rememberMeFilter, SecurityFilters.REMEMBER_ME_FILTER)); } - if (this.logoutFilter != null) { filters.add(new OrderDecorator(this.logoutFilter, SecurityFilters.LOGOUT_FILTER)); } - if (this.x509Filter != null) { filters.add(new OrderDecorator(this.x509Filter, SecurityFilters.X509_FILTER)); } - if (this.jeeFilter != null) { filters.add(new OrderDecorator(this.jeeFilter, SecurityFilters.PRE_AUTH_FILTER)); } - if (this.formFilterId != null) { filters.add( new OrderDecorator(new RuntimeBeanReference(this.formFilterId), SecurityFilters.FORM_LOGIN_FILTER)); } - if (this.oauth2LoginFilterId != null) { filters.add(new OrderDecorator(new RuntimeBeanReference(this.oauth2LoginFilterId), SecurityFilters.OAUTH2_LOGIN_FILTER)); filters.add(new OrderDecorator(this.oauth2AuthorizationRequestRedirectFilter, SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER)); } - if (this.openIDFilterId != null) { filters.add( new OrderDecorator(new RuntimeBeanReference(this.openIDFilterId), SecurityFilters.OPENID_FILTER)); } - if (this.loginPageGenerationFilter != null) { filters.add(new OrderDecorator(this.loginPageGenerationFilter, SecurityFilters.LOGIN_PAGE_FILTER)); filters.add(new OrderDecorator(this.logoutPageGenerationFilter, SecurityFilters.LOGOUT_PAGE_FILTER)); } - if (this.basicFilter != null) { filters.add(new OrderDecorator(this.basicFilter, SecurityFilters.BASIC_AUTH_FILTER)); } - if (this.bearerTokenAuthenticationFilter != null) { filters.add( new OrderDecorator(this.bearerTokenAuthenticationFilter, SecurityFilters.BEARER_TOKEN_AUTH_FILTER)); } - if (this.authorizationCodeGrantFilter != null) { filters.add(new OrderDecorator(this.authorizationRequestRedirectFilter, SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER.getOrder() + 1)); filters.add(new OrderDecorator(this.authorizationCodeGrantFilter, SecurityFilters.OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER)); } - filters.add(new OrderDecorator(this.etf, SecurityFilters.EXCEPTION_TRANSLATION_FILTER)); - return filters; } List getProviders() { List providers = new ArrayList<>(); - if (this.anonymousProviderRef != null) { providers.add(this.anonymousProviderRef); } - if (this.rememberMeProviderRef != null) { providers.add(this.rememberMeProviderRef); } - if (this.openIDProviderRef != null) { providers.add(this.openIDProviderRef); } - if (this.x509ProviderRef != null) { providers.add(this.x509ProviderRef); } - if (this.jeeProviderRef != null) { providers.add(this.jeeProviderRef); } - if (this.oauth2LoginAuthenticationProviderRef != null) { providers.add(this.oauth2LoginAuthenticationProviderRef); } - if (this.oauth2LoginOidcAuthenticationProviderRef != null) { providers.add(this.oauth2LoginOidcAuthenticationProviderRef); } - if (this.authorizationCodeAuthenticationProviderRef != null) { providers.add(this.authorizationCodeAuthenticationProviderRef); } - providers.addAll(this.authenticationProviders); - return providers; } diff --git a/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java b/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java index 0f2d649d08..6c00919429 100644 --- a/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java +++ b/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java @@ -43,7 +43,6 @@ public final class ChannelAttributeFactory { public static List createChannelAttributes(String requiredChannel) { String channelConfigAttribute; - if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) { channelConfigAttribute = "REQUIRES_SECURE_CHANNEL"; } @@ -56,7 +55,6 @@ public final class ChannelAttributeFactory { else { throw new BeanCreationException("Unknown channel attribute " + requiredChannel); } - return SecurityConfig.createList(channelConfigAttribute); } diff --git a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java index 8430cc8f1b..8f7ccc1eab 100644 --- a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java @@ -46,17 +46,14 @@ public class CorsBeanDefinitionParser { if (element == null) { return null; } - String filterRef = element.getAttribute(ATT_REF); if (StringUtils.hasText(filterRef)) { return new RuntimeBeanReference(filterRef); } - BeanMetadataElement configurationSource = getSource(element, parserContext); if (configurationSource == null) { throw new BeanCreationException("Could not create CorsFilter"); } - BeanDefinitionBuilder filterBldr = BeanDefinitionBuilder.rootBeanDefinition(CorsFilter.class); filterBldr.addConstructorArgValue(configurationSource); return filterBldr.getBeanDefinition(); @@ -67,12 +64,10 @@ public class CorsBeanDefinitionParser { if (StringUtils.hasText(configurationSourceRef)) { return new RuntimeBeanReference(configurationSourceRef); } - boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, getClass().getClassLoader()); if (!mvcPresent) { return null; } - return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class); } diff --git a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java index d5dcd2d7a1..58dcd468a8 100644 --- a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java @@ -92,14 +92,11 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { pc.registerBeanComponent(componentDefinition); } } - if (element != null) { this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY); this.requestMatcherRef = element.getAttribute(ATT_MATCHER); } - if (!StringUtils.hasText(this.csrfRepositoryRef)) { - RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class); BeanDefinitionBuilder lazyTokenRepository = BeanDefinitionBuilder .rootBeanDefinition(LazyCsrfTokenRepository.class); @@ -108,14 +105,11 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { pc.registerBeanComponent( new BeanComponentDefinition(lazyTokenRepository.getBeanDefinition(), this.csrfRepositoryRef)); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class); builder.addConstructorArgReference(this.csrfRepositoryRef); - if (StringUtils.hasText(this.requestMatcherRef)) { builder.addPropertyReference("requireCsrfProtectionMatcher", this.requestMatcherRef); } - this.csrfFilter = builder.getBeanDefinition(); return this.csrfFilter; } @@ -155,12 +149,10 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { .rootBeanDefinition(InvalidSessionAccessDeniedHandler.class); invalidSessionHandlerBldr.addConstructorArgValue(invalidSessionStrategy); handlers.put(MissingCsrfTokenException.class, invalidSessionHandlerBldr.getBeanDefinition()); - BeanDefinitionBuilder deniedBldr = BeanDefinitionBuilder .rootBeanDefinition(DelegatingAccessDeniedHandler.class); deniedBldr.addConstructorArgValue(handlers); deniedBldr.addConstructorArgValue(defaultDeniedHandler); - return deniedBldr.getBeanDefinition(); } @@ -180,13 +172,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { void setIgnoreCsrfRequestMatchers(List requestMatchers) { if (!requestMatchers.isEmpty()) { - BeanMetadataElement requestMatcher; - if (StringUtils.hasText(this.requestMatcherRef)) { - requestMatcher = new RuntimeBeanReference(this.requestMatcherRef); - } - else { - requestMatcher = new RootBeanDefinition(DefaultRequiresCsrfMatcher.class); - } + BeanMetadataElement requestMatcher = (!StringUtils.hasText(this.requestMatcherRef)) + ? new RootBeanDefinition(DefaultRequiresCsrfMatcher.class) + : new RuntimeBeanReference(this.requestMatcherRef); BeanDefinitionBuilder and = BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class); BeanDefinitionBuilder negated = BeanDefinitionBuilder.rootBeanDefinition(NegatedRequestMatcher.class); BeanDefinitionBuilder or = BeanDefinitionBuilder.rootBeanDefinition(OrRequestMatcher.class); diff --git a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java index 563794cdf7..423ae18de6 100644 --- a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java +++ b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java @@ -58,7 +58,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain checkLoginPageIsntProtected(fcp, filterChain.getFilters()); checkFilterStack(filterChain.getFilters()); } - checkPathOrder(new ArrayList<>(fcp.getFilterChains())); checkForDuplicateMatchers(new ArrayList<>(fcp.getFilterChains())); } @@ -66,7 +65,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain private void checkPathOrder(List filterChains) { // Check that the universal pattern is listed at the end, if at all Iterator chains = filterChains.iterator(); - while (chains.hasNext()) { RequestMatcher matcher = ((DefaultSecurityFilterChain) chains.next()).getRequestMatcher(); if (AnyRequestMatcher.INSTANCE.equals(matcher) && chains.hasNext()) { @@ -78,10 +76,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } private void checkForDuplicateMatchers(List chains) { - while (chains.size() > 1) { DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain) chains.remove(0); - for (SecurityFilterChain test : chains) { if (chain.getRequestMatcher().equals(((DefaultSecurityFilterChain) test).getRequestMatcher())) { throw new IllegalArgumentException("The FilterChainProxy contains two filter chains using the" @@ -99,7 +95,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return (F) f; } } - return null; } @@ -140,16 +135,13 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain */ private void checkLoginPageIsntProtected(FilterChainProxy fcp, List filterStack) { ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, filterStack); - if (etf == null || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) { return; } - String loginPage = ((LoginUrlAuthenticationEntryPoint) etf.getAuthenticationEntryPoint()).getLoginFormUrl(); this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration"); FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST"); List filters = null; - try { filters = fcp.getFilters(loginPage); } @@ -159,22 +151,17 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain // by the dummy request used when creating the filter invocation. this.logger.info("Failed to obtain filter chain information for the login page. Unable to complete check."); } - if (filters == null || filters.isEmpty()) { this.logger.debug("Filter chain is empty for the login page"); return; } - if (getFilter(DefaultLoginPageGeneratingFilter.class, filters) != null) { this.logger.debug("Default generated login page is in use"); return; } - FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, filters); FilterInvocationSecurityMetadataSource fids = fsi.getSecurityMetadataSource(); - Collection attributes = fids.getAttributes(loginRequest); - if (attributes == null) { this.logger.debug("No access attributes defined for login page URL"); if (fsi.isRejectPublicInvocations()) { @@ -183,14 +170,12 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } return; } - AnonymousAuthenticationFilter anonPF = getFilter(AnonymousAuthenticationFilter.class, filters); if (anonPF == null) { this.logger.warn("The login page is being protected by the filter chain, but you don't appear to have" + " anonymous authentication enabled. This is almost certainly an error."); return; } - // Simulate an anonymous access with the supplied attributes. AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getPrincipal(), anonPF.getAuthorities()); @@ -198,18 +183,16 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain fsi.getAccessDecisionManager().decide(token, loginRequest, attributes); } catch (AccessDeniedException ex) { - this.logger - .warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly " - + "an error. Please check your configuration allows unauthenticated access to the configured " - + "login page. (Simulated access was rejected: " + ex + ")"); + this.logger.warn("Anonymous access to the login page doesn't appear to be enabled. " + + "This is almost certainly an error. Please check your configuration allows unauthenticated " + + "access to the configured login page. (Simulated access was rejected: " + ex + ")"); } catch (Exception ex) { // May happen legitimately if a filter-chain request matcher requires more // request data than that provided // by the dummy request used when creating the filter invocation. See SEC-1878 - this.logger.info( - "Unable to check access to the login page to determine if anonymous access is allowed. This might be an error, but can happen under normal circumstances.", - ex); + this.logger.info("Unable to check access to the login page to determine if anonymous access is allowed. " + + "This might be an error, but can happen under normal circumstances.", ex); } } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java index 2d87afe5e6..c362bcc0a1 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java @@ -43,9 +43,7 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { String path = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); String requestMatcher = elt.getAttribute(ATT_REQUEST_MATCHER_REF); String filters = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultSecurityFilterChain.class); - if (StringUtils.hasText(path)) { Assert.isTrue(!StringUtils.hasText(requestMatcher), ""); builder.addConstructorArgValue(matcherType.createMatcher(pc, path, null)); @@ -54,21 +52,17 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { Assert.isTrue(StringUtils.hasText(requestMatcher), ""); builder.addConstructorArgReference(requestMatcher); } - if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) { builder.addConstructorArgValue(Collections.EMPTY_LIST); } else { String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ","); ManagedList filterChain = new ManagedList<>(filterBeanNames.length); - for (String name : filterBeanNames) { filterChain.add(new RuntimeBeanReference(name)); } - builder.addConstructorArgValue(filterChain); } - return builder.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java b/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java index ce2f0d9c96..842ac8799f 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java @@ -45,48 +45,36 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco @SuppressWarnings("unchecked") public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { BeanDefinition filterChainProxy = holder.getBeanDefinition(); - ManagedList securityFilterChains = new ManagedList<>(); Element elt = (Element) node; - MatcherType matcherType = MatcherType.fromElement(elt); - List filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN); - for (Element chain : filterChainElts) { String path = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); - if (!StringUtils.hasText(path)) { parserContext.getReaderContext().error( "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN + "' must not be empty", elt); } - if (!StringUtils.hasText(filters)) { parserContext.getReaderContext().error( "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "'must not be empty", elt); } - BeanDefinition matcher = matcherType.createMatcher(parserContext, path, null); - if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) { securityFilterChains.add(createSecurityFilterChain(matcher, new ManagedList(0))); } else { String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ","); ManagedList filterChain = new ManagedList(filterBeanNames.length); - for (String name : filterBeanNames) { filterChain.add(new RuntimeBeanReference(name)); } - securityFilterChains.add(createSecurityFilterChain(matcher, filterChain)); } } - filterChainProxy.getConstructorArgumentValues().addGenericArgumentValue(securityFilterChains); - return holder; } 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 f0dc125778..abc7929438 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 @@ -64,35 +64,28 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit @Override public BeanDefinition parse(Element element, ParserContext parserContext) { List interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL); - // Check for attributes that aren't allowed in this context for (Element elt : interceptUrls) { if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL + "' isn't allowed here.", elt); } - if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { parserContext.getReaderContext().error( "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "' isn't allowed here.", elt); } - if (StringUtils.hasLength(elt.getAttribute(ATT_SERVLET_PATH))) { parserContext.getReaderContext().error("The attribute '" + ATT_SERVLET_PATH + "' isn't allowed here.", elt); } } - BeanDefinition mds = createSecurityMetadataSource(interceptUrls, false, element, parserContext); - String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE); - if (StringUtils.hasText(id)) { parserContext.registerComponent(new BeanComponentDefinition(mds, id)); parserContext.getRegistry().registerBeanDefinition(id, mds); } - return mds; } @@ -100,24 +93,20 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit Element httpElt, ParserContext pc) { MatcherType matcherType = MatcherType.fromElement(httpElt); boolean useExpressions = isUseExpressions(httpElt); - ManagedMap requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap( matcherType, interceptUrls, useExpressions, addAllAuth, pc); BeanDefinitionBuilder fidsBuilder; - if (useExpressions) { Element expressionHandlerElt = DomUtils.getChildElementByTagName(httpElt, Elements.EXPRESSION_HANDLER); String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref") : null; - if (StringUtils.hasText(expressionHandlerRef)) { - logger.info( - "Using bean '" + expressionHandlerRef + "' as web SecurityExpressionHandler implementation"); + logger.info("Using bean '" + expressionHandlerRef + "' as web " + + "SecurityExpressionHandler implementation"); } else { expressionHandlerRef = registerDefaultExpressionHandler(pc); } - fidsBuilder = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedFilterInvocationSecurityMetadataSource.class); fidsBuilder.addConstructorArgValue(requestToAttributesMap); @@ -127,9 +116,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class); fidsBuilder.addConstructorArgValue(requestToAttributesMap); } - fidsBuilder.getRawBeanDefinition().setSource(pc.extractSource(httpElt)); - return (RootBeanDefinition) fidsBuilder.getBeanDefinition(); } @@ -138,7 +125,6 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit DefaultWebSecurityExpressionHandlerBeanFactory.class); String expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler); pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef)); - return expressionHandlerRef; } @@ -150,28 +136,22 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit private static ManagedMap parseInterceptUrlsForFilterInvocationRequestMap( MatcherType matcherType, List urlElts, boolean useExpressions, boolean addAuthenticatedAll, ParserContext parserContext) { - ManagedMap filterInvocationDefinitionMap = new ManagedMap<>(); - for (Element urlElt : urlElts) { String access = urlElt.getAttribute(ATT_ACCESS); if (!StringUtils.hasText(access)) { continue; } - String path = urlElt.getAttribute(ATT_PATTERN); String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF); boolean hasMatcherRef = StringUtils.hasText(matcherRef); - if (!hasMatcherRef && !StringUtils.hasText(path)) { parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt); } - String method = urlElt.getAttribute(ATT_HTTP_METHOD); if (!StringUtils.hasText(method)) { method = null; } - String servletPath = urlElt.getAttribute(ATT_SERVLET_PATH); if (!StringUtils.hasText(servletPath)) { servletPath = null; @@ -181,11 +161,9 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt); } - BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(parserContext, path, method, servletPath); BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); - if (useExpressions) { logger.info("Creating access control expression attribute '" + access + "' for " + path); // The single expression will be parsed later by the @@ -198,23 +176,18 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit attributeBuilder.addConstructorArgValue(access); attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString"); } - if (filterInvocationDefinitionMap.containsKey(matcher)) { logger.warn("Duplicate URL defined: " + path + ". The original attribute values will be overwritten"); } - filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition()); } - if (addAuthenticatedAll && filterInvocationDefinitionMap.isEmpty()) { - BeanDefinition matcher = matcherType.createMatcher(parserContext, "/**", null); BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); attributeBuilder.addConstructorArgValue(new String[] { "authenticated" }); attributeBuilder.setFactoryMethod("createList"); filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition()); } - return filterInvocationDefinitionMap; } diff --git a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java index c39c6a303a..e29bed8283 100644 --- a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java @@ -123,9 +123,7 @@ public class FormLoginBeanDefinitionParser { String authDetailsSourceRef = null; String authenticationFailureForwardUrl = null; String authenticationSuccessForwardUrl = null; - Object source = null; - if (elt != null) { source = pc.extractSource(elt); loginUrl = elt.getAttribute(ATT_LOGIN_URL); @@ -143,7 +141,6 @@ public class FormLoginBeanDefinitionParser { WebConfigUtils.validateHttpRedirect(authenticationFailureForwardUrl, pc, source); authenticationSuccessForwardUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_SUCCESS_FORWARD_URL); WebConfigUtils.validateHttpRedirect(authenticationSuccessForwardUrl, pc, source); - if (!StringUtils.hasText(this.loginPage)) { this.loginPage = null; } @@ -151,20 +148,16 @@ public class FormLoginBeanDefinitionParser { usernameParameter = elt.getAttribute(ATT_USERNAME_PARAMETER); passwordParameter = elt.getAttribute(ATT_PASSWORD_PARAMETER); } - this.filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, this.loginPage, authenticationFailureUrl, successHandlerRef, failureHandlerRef, authDetailsSourceRef, authenticationFailureForwardUrl, authenticationSuccessForwardUrl); - if (StringUtils.hasText(usernameParameter)) { this.filterBean.getPropertyValues().addPropertyValue("usernameParameter", usernameParameter); } if (StringUtils.hasText(passwordParameter)) { this.filterBean.getPropertyValues().addPropertyValue("passwordParameter", passwordParameter); } - this.filterBean.setSource(source); - BeanDefinitionBuilder entryPointBuilder = BeanDefinitionBuilder .rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class); entryPointBuilder.getRawBeanDefinition().setSource(source); @@ -172,7 +165,6 @@ public class FormLoginBeanDefinitionParser { entryPointBuilder.addPropertyValue("portMapper", this.portMapper); entryPointBuilder.addPropertyValue("portResolver", this.portResolver); this.entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition(); - return null; } @@ -180,24 +172,18 @@ public class FormLoginBeanDefinitionParser { String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef, String authDetailsSourceRef, String authenticationFailureForwardUrl, String authenticationSuccessForwardUrl) { - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(this.filterClassName); - if (!StringUtils.hasText(loginUrl)) { loginUrl = this.defaultLoginProcessingUrl; } - this.loginProcessingUrl = loginUrl; - BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder .rootBeanDefinition("org.springframework.security.web.util.matcher.AntPathRequestMatcher"); matcherBuilder.addConstructorArgValue(loginUrl); if (this.loginMethod != null) { matcherBuilder.addConstructorArgValue("POST"); } - filterBuilder.addPropertyValue("requiresAuthenticationRequestMatcher", matcherBuilder.getBeanDefinition()); - if (StringUtils.hasText(successHandlerRef)) { filterBuilder.addPropertyReference("authenticationSuccessHandler", successHandlerRef); } @@ -218,15 +204,12 @@ public class FormLoginBeanDefinitionParser { StringUtils.hasText(defaultTargetUrl) ? defaultTargetUrl : DEF_FORM_LOGIN_TARGET_URL); filterBuilder.addPropertyValue("authenticationSuccessHandler", successHandler.getBeanDefinition()); } - if (StringUtils.hasText(authDetailsSourceRef)) { filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef); } - if (this.sessionStrategy != null) { filterBuilder.addPropertyValue("sessionAuthenticationStrategy", this.sessionStrategy); } - if (StringUtils.hasText(failureHandlerRef)) { filterBuilder.addPropertyReference("authenticationFailureHandler", failureHandlerRef); } @@ -252,7 +235,6 @@ public class FormLoginBeanDefinitionParser { failureHandler.addPropertyValue("allowSessionCreation", this.allowSessionCreation); filterBuilder.addPropertyValue("authenticationFailureHandler", failureHandler.getBeanDefinition()); } - return (RootBeanDefinition) filterBuilder.getBeanDefinition(); } 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 index ae7a2f8f27..ce32607100 100644 --- a/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java +++ b/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java @@ -37,7 +37,6 @@ final class GrantedAuthorityDefaultsParserUtils { 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"); diff --git a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java index 3b991a8d38..302e95834a 100644 --- a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java @@ -41,9 +41,11 @@ class HandlerMappingIntrospectorFactoryBean @Override public HandlerMappingIntrospector getObject() { if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " - + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); + throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, + "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + + HandlerMappingIntrospector.class.getName() + + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring " + + "MVC are configured in a shared ApplicationContext."); } return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); } diff --git a/config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java index c4f96eba3a..ac37bc76ab 100644 --- a/config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java @@ -125,32 +125,22 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext parserContext) { - this.headerWriters = new ManagedList<>(); BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(HeaderWriterFilter.class); - boolean disabled = element != null && "true".equals(resolveAttribute(parserContext, element, "disabled")); boolean defaultsDisabled = element != null && "true".equals(resolveAttribute(parserContext, element, "defaults-disabled")); - boolean addIfNotPresent = element == null || !disabled && !defaultsDisabled; - parseCacheControlElement(addIfNotPresent, element); parseHstsElement(addIfNotPresent, element, parserContext); parseXssElement(addIfNotPresent, element, parserContext); parseFrameOptionsElement(addIfNotPresent, element, parserContext); parseContentTypeOptionsElement(addIfNotPresent, element); - parseHpkpElement(element == null || !disabled, element, parserContext); - parseContentSecurityPolicyElement(disabled, element, parserContext); - parseReferrerPolicyElement(element, parserContext); - parseFeaturePolicyElement(element, parserContext); - parseHeaderElements(element); - boolean noWriters = this.headerWriters.isEmpty(); if (disabled && !noWriters) { parserContext.getReaderContext().error("Cannot specify with child elements.", @@ -159,13 +149,11 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { else if (noWriters) { return null; } - builder.addConstructorArgValue(this.headerWriters); return builder.getBeanDefinition(); } /** - * * Resolve the placeholder for a given attribute on a element. * @param pc * @param element @@ -233,7 +221,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } headersWriter.addPropertyValue("preload", preload); } - if (disabled) { return; } @@ -253,59 +240,45 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { private void addHpkp(boolean addIfNotPresent, Element hpkpElement, ParserContext context) { if (hpkpElement != null) { boolean disabled = "true".equals(getAttribute(hpkpElement, ATT_DISABLED, "false")); - if (disabled) { return; } - BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(HpkpHeaderWriter.class); - Element pinsElement = DomUtils.getChildElementByTagName(hpkpElement, PINS_ELEMENT); if (pinsElement != null) { List pinElements = DomUtils.getChildElements(pinsElement); - Map pins = new LinkedHashMap<>(); - for (Element pinElement : pinElements) { String hash = pinElement.getAttribute(ATT_ALGORITHM); if (!StringUtils.hasText(hash)) { hash = "sha256"; } - Node pinValueNode = pinElement.getFirstChild(); if (pinValueNode == null) { context.getReaderContext().warning("Missing value for pin entry.", hpkpElement); continue; } - String fingerprint = pinElement.getFirstChild().getTextContent(); - pins.put(fingerprint, hash); } - headersWriter.addPropertyValue("pins", pins); } - String includeSubDomains = hpkpElement.getAttribute(ATT_INCLUDE_SUBDOMAINS); if (StringUtils.hasText(includeSubDomains)) { headersWriter.addPropertyValue("includeSubDomains", includeSubDomains); } - String maxAgeSeconds = hpkpElement.getAttribute(ATT_MAX_AGE_SECONDS); if (StringUtils.hasText(maxAgeSeconds)) { headersWriter.addPropertyValue("maxAgeInSeconds", maxAgeSeconds); } - String reportOnly = hpkpElement.getAttribute(ATT_REPORT_ONLY); if (StringUtils.hasText(reportOnly)) { headersWriter.addPropertyValue("reportOnly", reportOnly); } - String reportUri = hpkpElement.getAttribute(ATT_REPORT_URI); if (StringUtils.hasText(reportUri)) { headersWriter.addPropertyValue("reportUri", reportUri); } - if (addIfNotPresent) { this.headerWriters.add(headersWriter.getBeanDefinition()); } @@ -323,7 +296,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { private void addContentSecurityPolicy(Element contentSecurityPolicyElement, ParserContext context) { BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder .genericBeanDefinition(ContentSecurityPolicyHeaderWriter.class); - String policyDirectives = contentSecurityPolicyElement.getAttribute(ATT_POLICY_DIRECTIVES); if (!StringUtils.hasText(policyDirectives)) { context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", @@ -332,12 +304,10 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { else { headersWriter.addConstructorArgValue(policyDirectives); } - String reportOnly = contentSecurityPolicyElement.getAttribute(ATT_REPORT_ONLY); if (StringUtils.hasText(reportOnly)) { headersWriter.addPropertyValue("reportOnly", reportOnly); } - this.headerWriters.add(headersWriter.getBeanDefinition()); } @@ -352,7 +322,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { private void addReferrerPolicy(Element referrerPolicyElement, ParserContext context) { BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder .genericBeanDefinition(ReferrerPolicyHeaderWriter.class); - String policy = referrerPolicyElement.getAttribute(ATT_POLICY); if (StringUtils.hasLength(policy)) { headersWriter.addConstructorArgValue(ReferrerPolicy.get(policy)); @@ -371,7 +340,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { private void addFeaturePolicy(Element featurePolicyElement, ParserContext context) { BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder .genericBeanDefinition(FeaturePolicyHeaderWriter.class); - String policyDirectives = featurePolicyElement.getAttribute(ATT_POLICY_DIRECTIVES); if (!StringUtils.hasText(policyDirectives)) { context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", @@ -380,7 +348,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { else { headersWriter.addConstructorArgValue(policyDirectives); } - this.headerWriters.add(headersWriter.getBeanDefinition()); } @@ -508,7 +475,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class); if (xssElt != null) { boolean disabled = "true".equals(getAttribute(xssElt, ATT_DISABLED, "false")); - String enabled = xssElt.getAttribute(ATT_ENABLED); if (StringUtils.hasText(enabled)) { if (disabled) { @@ -516,7 +482,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } builder.addPropertyValue("enabled", enabled); } - String block = xssElt.getAttribute(ATT_BLOCK); if (StringUtils.hasText(block)) { if (disabled) { @@ -524,7 +489,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } builder.addPropertyValue("block", block); } - if (disabled) { return; } @@ -542,9 +506,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { if (StringUtils.hasText(value)) { return value; } - else { - return defaultValue; - } + return defaultValue; } } 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 294d830a36..992d5c60a1 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 @@ -71,6 +71,7 @@ import org.springframework.security.web.session.SessionManagementFilter; 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.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -113,6 +114,22 @@ class HttpConfigurationBuilder { private static final String ATT_REF = "ref"; + private static final String ATT_EXPIRY_URL = "expired-url"; + + private static final String ATT_EXPIRED_SESSION_STRATEGY_REF = "expired-session-strategy-ref"; + + private static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias"; + + private static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref"; + + private static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision"; + + private static final String DEF_SERVLET_API_PROVISION = "true"; + + private static final String ATT_JAAS_API_PROVISION = "jaas-api-provision"; + + private static final String DEF_JAAS_API_PROVISION = "false"; + private final Element httpElt; private final ParserContext pc; @@ -178,25 +195,10 @@ class HttpConfigurationBuilder { this.portResolver = portResolver; this.matcherType = MatcherType.fromElement(element); this.interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL); - - for (Element urlElt : this.interceptUrls) { - if (StringUtils.hasText(urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { - pc.getReaderContext() - .error("The use of \"filters='none'\" is no longer supported. Please define a" - + " separate element for the pattern you want to exclude and use the attribute" - + " \"security='none'\".", pc.extractSource(urlElt)); - } - } - + validateInterceptUrls(pc); String createSession = element.getAttribute(ATT_CREATE_SESSION); - - if (StringUtils.hasText(createSession)) { - this.sessionPolicy = createPolicy(createSession); - } - else { - this.sessionPolicy = SessionCreationPolicy.IF_REQUIRED; - } - + this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED + : createPolicy(createSession); createCsrfFilter(); createSecurityContextPersistenceFilter(); createSessionManagementFilters(); @@ -210,20 +212,30 @@ class HttpConfigurationBuilder { createCorsFilter(); } + private void validateInterceptUrls(ParserContext pc) { + for (Element element : this.interceptUrls) { + if (StringUtils.hasText(element.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { + String message = "The use of \"filters='none'\" is no longer supported. Please define a" + + " separate element for the pattern you want to exclude and use the attribute" + + " \"security='none'\"."; + pc.getReaderContext().error(message, pc.extractSource(element)); + } + } + } + private SessionCreationPolicy createPolicy(String createSession) { if ("ifRequired".equals(createSession)) { return SessionCreationPolicy.IF_REQUIRED; } - else if ("always".equals(createSession)) { + if ("always".equals(createSession)) { return SessionCreationPolicy.ALWAYS; } - else if ("never".equals(createSession)) { + if ("never".equals(createSession)) { return SessionCreationPolicy.NEVER; } - else if ("stateless".equals(createSession)) { + if ("stateless".equals(createSession)) { return SessionCreationPolicy.STATELESS; } - throw new IllegalStateException( "Cannot convert " + createSession + " to " + SessionCreationPolicy.class.getName()); } @@ -265,13 +277,11 @@ class HttpConfigurationBuilder { private void createSecurityContextPersistenceFilter() { BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class); - String repoRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY); String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING); if (!StringUtils.hasText(disableUrlRewriting)) { disableUrlRewriting = "true"; } - if (StringUtils.hasText(repoRef)) { if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) { scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); @@ -297,12 +307,10 @@ class HttpConfigurationBuilder { contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); } - if ("true".equals(disableUrlRewriting)) { contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE); } } - BeanDefinition repoBean = contextRepo.getBeanDefinition(); repoRef = this.pc.getReaderContext().generateBeanName(repoBean); this.pc.registerBeanComponent(new BeanComponentDefinition(repoBean, repoRef)); @@ -317,13 +325,11 @@ class HttpConfigurationBuilder { private void createSessionManagementFilters() { Element sessionMgmtElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SESSION_MANAGEMENT); Element sessionCtrlElt = null; - String sessionFixationAttribute = null; String invalidSessionUrl = null; String invalidSessionStrategyRef = null; String sessionAuthStratRef = null; String errorUrl = null; - boolean sessionControlEnabled = false; if (sessionMgmtElt != null) { if (this.sessionPolicy == SessionCreationPolicy.STATELESS) { @@ -335,18 +341,15 @@ class HttpConfigurationBuilder { sessionFixationAttribute = sessionMgmtElt.getAttribute(ATT_SESSION_FIXATION_PROTECTION); invalidSessionUrl = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_URL); invalidSessionStrategyRef = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_STRATEGY_REF); - sessionAuthStratRef = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_STRATEGY_REF); errorUrl = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_ERROR_URL); sessionCtrlElt = DomUtils.getChildElementByTagName(sessionMgmtElt, Elements.CONCURRENT_SESSIONS); sessionControlEnabled = sessionCtrlElt != null; - if (StringUtils.hasText(invalidSessionUrl) && StringUtils.hasText(invalidSessionStrategyRef)) { this.pc.getReaderContext() .error(ATT_INVALID_SESSION_URL + " attribute cannot be used in combination with" + " the " + ATT_INVALID_SESSION_STRATEGY_REF + " attribute.", sessionMgmtElt); } - if (sessionControlEnabled) { if (StringUtils.hasText(sessionAuthStratRef)) { this.pc.getReaderContext() @@ -370,33 +373,25 @@ class HttpConfigurationBuilder { // SEC-1424: do nothing return; } - boolean sessionFixationProtectionRequired = !sessionFixationAttribute .equals(OPT_SESSION_FIXATION_NO_PROTECTION); - ManagedList delegateSessionStrategies = new ManagedList<>(); BeanDefinitionBuilder concurrentSessionStrategy; BeanDefinitionBuilder sessionFixationStrategy = null; BeanDefinitionBuilder registerSessionStrategy; - if (this.csrfAuthStrategy != null) { delegateSessionStrategies.add(this.csrfAuthStrategy); } - if (sessionControlEnabled) { - assert this.sessionRegistryRef != null; + Assert.state(this.sessionRegistryRef != null, "No sessionRegistryRef found"); concurrentSessionStrategy = BeanDefinitionBuilder .rootBeanDefinition(ConcurrentSessionControlAuthenticationStrategy.class); concurrentSessionStrategy.addConstructorArgValue(this.sessionRegistryRef); - String maxSessions = sessionCtrlElt.getAttribute("max-sessions"); - if (StringUtils.hasText(maxSessions)) { concurrentSessionStrategy.addPropertyValue("maximumSessions", maxSessions); } - String exceptionIfMaximumExceeded = sessionCtrlElt.getAttribute("error-if-maximum-exceeded"); - if (StringUtils.hasText(exceptionIfMaximumExceeded)) { concurrentSessionStrategy.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded); } @@ -414,23 +409,19 @@ class HttpConfigurationBuilder { } delegateSessionStrategies.add(sessionFixationStrategy.getBeanDefinition()); } - if (StringUtils.hasText(sessionAuthStratRef)) { delegateSessionStrategies.add(new RuntimeBeanReference(sessionAuthStratRef)); } - if (sessionControlEnabled) { registerSessionStrategy = BeanDefinitionBuilder .rootBeanDefinition(RegisterSessionAuthenticationStrategy.class); registerSessionStrategy.addConstructorArgValue(this.sessionRegistryRef); delegateSessionStrategies.add(registerSessionStrategy.getBeanDefinition()); } - if (delegateSessionStrategies.isEmpty()) { this.sfpf = null; return; } - BeanDefinitionBuilder sessionMgmtFilter = BeanDefinitionBuilder .rootBeanDefinition(SessionManagementFilter.class); RootBeanDefinition failureHandler = new RootBeanDefinition(SimpleUrlAuthenticationFailureHandler.class); @@ -439,15 +430,12 @@ class HttpConfigurationBuilder { } sessionMgmtFilter.addPropertyValue("authenticationFailureHandler", failureHandler); sessionMgmtFilter.addConstructorArgValue(this.contextRepoRef); - if (!StringUtils.hasText(sessionAuthStratRef) && sessionFixationStrategy != null && !useChangeSessionId) { - if (sessionFixationProtectionRequired) { sessionFixationStrategy.addPropertyValue("migrateSessionAttributes", sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)); } } - if (!delegateSessionStrategies.isEmpty()) { BeanDefinitionBuilder sessionStrategy = BeanDefinitionBuilder .rootBeanDefinition(CompositeSessionAuthenticationStrategy.class); @@ -455,9 +443,7 @@ class HttpConfigurationBuilder { sessionStrategy.addConstructorArgValue(delegateSessionStrategies); sessionAuthStratRef = this.pc.getReaderContext().generateBeanName(strategyBean); this.pc.registerBeanComponent(new BeanComponentDefinition(strategyBean, sessionAuthStratRef)); - } - if (StringUtils.hasText(invalidSessionUrl)) { BeanDefinitionBuilder invalidSessionBldr = BeanDefinitionBuilder .rootBeanDefinition(SimpleRedirectInvalidSessionStrategy.class); @@ -468,55 +454,39 @@ class HttpConfigurationBuilder { else if (StringUtils.hasText(invalidSessionStrategyRef)) { sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef); } - sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef); - this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition(); this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef); } private void createConcurrencyControlFilterAndSessionRegistry(Element element) { - final String ATT_EXPIRY_URL = "expired-url"; - final String ATT_EXPIRED_SESSION_STRATEGY_REF = "expired-session-strategy-ref"; - final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias"; - final String ATT_SESSION_REGISTRY_REF = "session-registry-ref"; - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), this.pc.extractSource(element)); this.pc.pushContainingComponent(compositeDef); - BeanDefinitionRegistry beanRegistry = this.pc.getRegistry(); - String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF); - if (!StringUtils.hasText(sessionRegistryId)) { // Register an internal SessionRegistryImpl if no external reference supplied. RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class); sessionRegistryId = this.pc.getReaderContext().registerWithGeneratedName(sessionRegistry); this.pc.registerComponent(new BeanComponentDefinition(sessionRegistry, sessionRegistryId)); } - String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS); if (StringUtils.hasText(registryAlias)) { beanRegistry.registerAlias(sessionRegistryId, registryAlias); } - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class); filterBuilder.addConstructorArgReference(sessionRegistryId); - Object source = this.pc.extractSource(element); filterBuilder.getRawBeanDefinition().setSource(source); filterBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - String expiryUrl = element.getAttribute(ATT_EXPIRY_URL); String expiredSessionStrategyRef = element.getAttribute(ATT_EXPIRED_SESSION_STRATEGY_REF); - if (StringUtils.hasText(expiryUrl) && StringUtils.hasText(expiredSessionStrategyRef)) { this.pc.getReaderContext().error( "Cannot use 'expired-url' attribute and 'expired-session-strategy-ref'" + " attribute together.", source); } - if (StringUtils.hasText(expiryUrl)) { BeanDefinitionBuilder expiredSessionBldr = BeanDefinitionBuilder .rootBeanDefinition(SimpleRedirectSessionInformationExpiredStrategy.class); @@ -526,9 +496,7 @@ class HttpConfigurationBuilder { else if (StringUtils.hasText(expiredSessionStrategyRef)) { filterBuilder.addConstructorArgReference(expiredSessionStrategyRef); } - this.pc.popAndRegisterContainingComponent(); - this.concurrentSessionFilter = filterBuilder.getBeanDefinition(); this.sessionRegistryRef = new RuntimeBeanReference(sessionRegistryId); } @@ -542,14 +510,10 @@ class HttpConfigurationBuilder { // Adds the servlet-api integration filter if required private void createServletApiFilter(BeanReference authenticationManager) { - final String ATT_SERVLET_API_PROVISION = "servlet-api-provision"; - final String DEF_SERVLET_API_PROVISION = "true"; - String provideServletApi = this.httpElt.getAttribute(ATT_SERVLET_API_PROVISION); if (!StringUtils.hasText(provideServletApi)) { provideServletApi = DEF_SERVLET_API_PROVISION; } - if ("true".equals(provideServletApi)) { this.servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(this.pc, SecurityContextHolderAwareRequestFilterBeanFactory.class); @@ -559,14 +523,10 @@ class HttpConfigurationBuilder { // Adds the jaas-api integration filter if required private void createJaasApiFilter() { - final String ATT_JAAS_API_PROVISION = "jaas-api-provision"; - final String DEF_JAAS_API_PROVISION = "false"; - String provideJaasApi = this.httpElt.getAttribute(ATT_JAAS_API_PROVISION); if (!StringUtils.hasText(provideJaasApi)) { provideJaasApi = DEF_JAAS_API_PROVISION; } - if ("true".equals(provideJaasApi)) { this.jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class); } @@ -574,18 +534,13 @@ class HttpConfigurationBuilder { private void createChannelProcessingFilter() { ManagedMap channelRequestMap = parseInterceptUrlsForChannelSecurity(); - if (channelRequestMap.isEmpty()) { return; } - RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class); BeanDefinitionBuilder metadataSourceBldr = BeanDefinitionBuilder .rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class); metadataSourceBldr.addConstructorArgValue(channelRequestMap); - // metadataSourceBldr.addPropertyValue("stripQueryStringFromUrls", matcher - // instanceof AntUrlPathMatcher); - channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource", metadataSourceBldr.getBeanDefinition()); RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class); @@ -593,7 +548,6 @@ class HttpConfigurationBuilder { RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class); RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class); RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class); - retryWithHttp.getPropertyValues().addPropertyValue("portMapper", this.portMapper); retryWithHttp.getPropertyValues().addPropertyValue("portResolver", this.portResolver); retryWithHttps.getPropertyValues().addPropertyValue("portMapper", this.portMapper); @@ -604,7 +558,6 @@ class HttpConfigurationBuilder { channelProcessors.add(secureChannelProcessor); channelProcessors.add(inSecureChannelProcessor); channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors); - String id = this.pc.getReaderContext().registerWithGeneratedName(channelDecisionManager); channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(id)); this.cpf = channelFilter; @@ -616,45 +569,35 @@ class HttpConfigurationBuilder { * path. */ private ManagedMap parseInterceptUrlsForChannelSecurity() { - ManagedMap channelRequestMap = new ManagedMap<>(); - for (Element urlElt : this.interceptUrls) { String path = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); String method = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_HTTP_METHOD); String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF); boolean hasMatcherRef = StringUtils.hasText(matcherRef); - if (!hasMatcherRef && !StringUtils.hasText(path)) { this.pc.getReaderContext().error("pattern attribute cannot be empty or null", urlElt); } - String requiredChannel = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL); - if (StringUtils.hasText(requiredChannel)) { BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : this.matcherType.createMatcher(this.pc, path, method); - RootBeanDefinition channelAttributes = new RootBeanDefinition(ChannelAttributeFactory.class); channelAttributes.getConstructorArgumentValues().addGenericArgumentValue(requiredChannel); channelAttributes.setFactoryMethodName("createChannelAttributes"); - channelRequestMap.put(matcher, channelAttributes); } } - return channelRequestMap; } private void createRequestCacheFilter() { Element requestCacheElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REQUEST_CACHE); - if (requestCacheElt != null) { this.requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF)); } else { BeanDefinitionBuilder requestCacheBldr; - if (this.sessionPolicy == SessionCreationPolicy.STATELESS) { requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(NullRequestCache.class); } @@ -671,14 +614,11 @@ class HttpConfigurationBuilder { requestCacheBldr.addPropertyValue("requestMatcher", requestCacheMatcherBldr.getBeanDefinition()); } } - BeanDefinition bean = requestCacheBldr.getBeanDefinition(); String id = this.pc.getReaderContext().generateBeanName(bean); this.pc.registerBeanComponent(new BeanComponentDefinition(bean, id)); - this.requestCache = new RuntimeBeanReference(id); } - this.requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class); this.requestCacheAwareFilter.getConstructorArgumentValues().addGenericArgumentValue(this.requestCache); } @@ -687,18 +627,14 @@ class HttpConfigurationBuilder { boolean useExpressions = FilterInvocationSecurityMetadataSourceParser.isUseExpressions(this.httpElt); RootBeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser .createSecurityMetadataSource(this.interceptUrls, this.addAllAuth, this.httpElt, this.pc); - RootBeanDefinition accessDecisionMgr; ManagedList voters = new ManagedList<>(2); - if (useExpressions) { BeanDefinitionBuilder expressionVoter = BeanDefinitionBuilder.rootBeanDefinition(WebExpressionVoter.class); // Read the expression handler from the FISMS RuntimeBeanReference expressionHandler = (RuntimeBeanReference) securityMds.getConstructorArgumentValues() .getArgumentValue(1, RuntimeBeanReference.class).getValue(); - expressionVoter.addPropertyValue("expressionHandler", expressionHandler); - voters.add(expressionVoter.getBeanDefinition()); } else { @@ -709,37 +645,28 @@ class HttpConfigurationBuilder { accessDecisionMgr = new RootBeanDefinition(AffirmativeBased.class); accessDecisionMgr.getConstructorArgumentValues().addGenericArgumentValue(voters); accessDecisionMgr.setSource(this.pc.extractSource(this.httpElt)); - // Set up the access manager reference for http String accessManagerId = this.httpElt.getAttribute(ATT_ACCESS_MGR); - if (!StringUtils.hasText(accessManagerId)) { accessManagerId = this.pc.getReaderContext().generateBeanName(accessDecisionMgr); this.pc.registerBeanComponent(new BeanComponentDefinition(accessDecisionMgr, accessManagerId)); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); - builder.addPropertyReference("accessDecisionManager", accessManagerId); builder.addPropertyValue("authenticationManager", authManager); - if ("false".equals(this.httpElt.getAttribute(ATT_ONCE_PER_REQUEST))) { builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE); } - builder.addPropertyValue("securityMetadataSource", securityMds); BeanDefinition fsiBean = builder.getBeanDefinition(); String fsiId = this.pc.getReaderContext().generateBeanName(fsiBean); this.pc.registerBeanComponent(new BeanComponentDefinition(fsiBean, fsiId)); - // Create and register a DefaultWebInvocationPrivilegeEvaluator for use with // taglibs etc. BeanDefinition wipe = new RootBeanDefinition(DefaultWebInvocationPrivilegeEvaluator.class); wipe.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(fsiId)); - this.pc.registerBeanComponent( new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe))); - this.fsi = new RuntimeBeanReference(fsiId); } @@ -758,12 +685,10 @@ class HttpConfigurationBuilder { Element elmt = DomUtils.getChildElementByTagName(this.httpElt, Elements.CSRF); this.csrfParser = new CsrfBeanDefinitionParser(); this.csrfFilter = this.csrfParser.parse(elmt, this.pc); - if (this.csrfFilter == null) { this.csrfParser = null; return; } - this.csrfAuthStrategy = this.csrfParser.getCsrfAuthenticationStrategy(); this.csrfLogoutHandler = this.csrfParser.getCsrfLogoutHandler(); } @@ -786,51 +711,38 @@ class HttpConfigurationBuilder { List getFilters() { List filters = new ArrayList<>(); - if (this.cpf != null) { filters.add(new OrderDecorator(this.cpf, SecurityFilters.CHANNEL_FILTER)); } - if (this.concurrentSessionFilter != null) { filters.add(new OrderDecorator(this.concurrentSessionFilter, SecurityFilters.CONCURRENT_SESSION_FILTER)); } - if (this.webAsyncManagerFilter != null) { filters.add(new OrderDecorator(this.webAsyncManagerFilter, SecurityFilters.WEB_ASYNC_MANAGER_FILTER)); } - filters.add(new OrderDecorator(this.securityContextPersistenceFilter, SecurityFilters.SECURITY_CONTEXT_FILTER)); - if (this.servApiFilter != null) { filters.add(new OrderDecorator(this.servApiFilter, SecurityFilters.SERVLET_API_SUPPORT_FILTER)); } - if (this.jaasApiFilter != null) { filters.add(new OrderDecorator(this.jaasApiFilter, SecurityFilters.JAAS_API_SUPPORT_FILTER)); } - if (this.sfpf != null) { filters.add(new OrderDecorator(this.sfpf, SecurityFilters.SESSION_MANAGEMENT_FILTER)); } - filters.add(new OrderDecorator(this.fsi, SecurityFilters.FILTER_SECURITY_INTERCEPTOR)); - if (this.sessionPolicy != SessionCreationPolicy.STATELESS) { filters.add(new OrderDecorator(this.requestCacheAwareFilter, SecurityFilters.REQUEST_CACHE_FILTER)); } - if (this.corsFilter != null) { filters.add(new OrderDecorator(this.corsFilter, SecurityFilters.CORS_FILTER)); } - if (this.addHeadersFilter != null) { filters.add(new OrderDecorator(this.addHeadersFilter, SecurityFilters.HEADERS_FILTER)); } - if (this.csrfFilter != null) { filters.add(new OrderDecorator(this.csrfFilter, SecurityFilters.CSRF_FILTER)); } - return filters; } diff --git a/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java index eaba9f3896..2a166c662d 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java @@ -36,16 +36,13 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext pc) { String ref = element.getAttribute("ref"); - if (!StringUtils.hasText(ref)) { pc.getReaderContext().error("ref attribute is required", pc.extractSource(element)); } - // Ensure the FCP is registered. HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, pc.extractSource(element)); BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY); filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref)); - return null; } diff --git a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java index c63a70eab9..970245d134 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java @@ -69,11 +69,15 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { private static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class); private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref"; + static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref"; + static final String ATT_PATH_PATTERN = "pattern"; + static final String ATT_HTTP_METHOD = "method"; static final String ATT_FILTERS = "filters"; + static final String OPT_FILTERS_NONE = "none"; static final String ATT_REQUIRES_CHANNEL = "requires-channel"; @@ -84,6 +88,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { private static final String OPT_SECURITY_NONE = "none"; + private static final String ATT_AFTER = "after"; + + private static final String ATT_BEFORE = "before"; + + private static final String ATT_POSITION = "position"; + public HttpSecurityBeanDefinitionParser() { } @@ -102,16 +112,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)); pc.pushContainingComponent(compositeDef); - registerFilterChainProxyIfNecessary(pc, pc.extractSource(element)); - // Obtain the filter chains and add the new chain to it BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS); List filterChains = (List) listFactoryBean.getPropertyValues() .getPropertyValue("sourceList").getValue(); - filterChains.add(createFilterChain(element, pc)); - pc.popAndRegisterContainingComponent(); return null; } @@ -121,76 +127,62 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { */ private BeanReference createFilterChain(Element element, ParserContext pc) { boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED)); - if (!secured) { - if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN)) - && !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) { - pc.getReaderContext() - .error("The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '" - + ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.", - pc.extractSource(element)); - } - - for (int n = 0; n < element.getChildNodes().getLength(); n++) { - if (element.getChildNodes().item(n) instanceof Element) { + validateSecuredFilterChainElement(element, pc); + for (int i = 0; i < element.getChildNodes().getLength(); i++) { + if (element.getChildNodes().item(i) instanceof Element) { pc.getReaderContext().error("If you are using to define an unsecured pattern, " + "it cannot contain child elements.", pc.extractSource(element)); } } - return createSecurityFilterChainBean(element, pc, Collections.emptyList()); } - - final BeanReference portMapper = createPortMapper(element, pc); - final BeanReference portResolver = createPortResolver(portMapper, pc); - + BeanReference portMapper = createPortMapper(element, pc); + BeanReference portResolver = createPortResolver(portMapper, pc); ManagedList authenticationProviders = new ManagedList<>(); BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders); - boolean forceAutoConfig = isDefaultHttpConfig(element); HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper, portResolver, authenticationManager); - AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc, httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager, httpBldr.getSessionStrategy(), portMapper, portResolver, httpBldr.getCsrfLogoutHandler()); - httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers()); httpBldr.setEntryPoint(authBldr.getEntryPointBean()); httpBldr.setAccessDeniedHandler(authBldr.getAccessDeniedHandlerBean()); httpBldr.setCsrfIgnoreRequestMatchers(authBldr.getCsrfIgnoreRequestMatchers()); - authenticationProviders.addAll(authBldr.getProviders()); - List unorderedFilterChain = new ArrayList<>(); - unorderedFilterChain.addAll(httpBldr.getFilters()); unorderedFilterChain.addAll(authBldr.getFilters()); unorderedFilterChain.addAll(buildCustomFilterList(element, pc)); - unorderedFilterChain.sort(new OrderComparator()); checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element)); - // The list of filter beans List filterChain = new ManagedList<>(); - for (OrderDecorator od : unorderedFilterChain) { filterChain.add(od.bean); } - return createSecurityFilterChainBean(element, pc, filterChain); } + private void validateSecuredFilterChainElement(Element element, ParserContext pc) { + if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN)) + && !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) { + String message = "The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '" + + ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes."; + pc.getReaderContext().error(message, pc.extractSource(element)); + } + } + private static boolean isDefaultHttpConfig(Element httpElt) { return httpElt.getChildNodes().getLength() == 0 && httpElt.getAttributes().getLength() == 0; } private BeanReference createSecurityFilterChainBean(Element element, ParserContext pc, List filterChain) { BeanMetadataElement filterChainMatcher; - String requestMatcherRef = element.getAttribute(ATT_REQUEST_MATCHER_REF); String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN); - if (StringUtils.hasText(requestMatcherRef)) { if (StringUtils.hasText(filterChainPattern)) { pc.getReaderContext().error( @@ -206,14 +198,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { else { filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class); } - BeanDefinitionBuilder filterChainBldr = BeanDefinitionBuilder .rootBeanDefinition(DefaultSecurityFilterChain.class); filterChainBldr.addConstructorArgValue(filterChainMatcher); filterChainBldr.addConstructorArgValue(filterChain); - BeanDefinition filterChainBean = filterChainBldr.getBeanDefinition(); - String id = element.getAttribute("name"); if (!StringUtils.hasText(id)) { id = element.getAttribute("id"); @@ -221,9 +210,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { id = pc.getReaderContext().generateBeanName(filterChainBean); } } - pc.registerBeanComponent(new BeanComponentDefinition(filterChainBean, id)); - return new RuntimeBeanReference(id); } @@ -234,7 +221,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { .parse(DomUtils.getChildElementByTagName(elt, Elements.PORT_MAPPINGS), pc); String portMapperName = pc.getReaderContext().generateBeanName(portMapper); pc.registerBeanComponent(new BeanComponentDefinition(portMapper, portMapperName)); - return new RuntimeBeanReference(portMapperName); } @@ -259,7 +245,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { String parentMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF); BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class); authManager.addConstructorArgValue(authenticationProviders); - if (StringUtils.hasText(parentMgrRef)) { RuntimeBeanReference parentAuthManager = new RuntimeBeanReference(parentMgrRef); authManager.addConstructorArgValue(parentAuthManager); @@ -268,7 +253,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { clearCredentials.getPropertyValues().addPropertyValue("targetObject", parentAuthManager); clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication"); - authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials); } else { @@ -280,11 +264,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RuntimeBeanReference(amfbId)); clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication"); - authManager.addConstructorArgValue(new RuntimeBeanReference(amfbId)); authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials); } - // gh-6009 authManager.addPropertyValue("authenticationEventPublisher", new RootBeanDefinition(DefaultAuthenticationEventPublisher.class)); @@ -292,16 +274,13 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { BeanDefinition authMgrBean = authManager.getBeanDefinition(); String id = pc.getReaderContext().generateBeanName(authMgrBean); pc.registerBeanComponent(new BeanComponentDefinition(authMgrBean, id)); - return new RuntimeBeanReference(id); } private void checkFilterChainOrder(List filters, ParserContext pc, Object source) { logger.info("Checking sorted filter chain: " + filters); - for (int i = 0; i < filters.size(); i++) { OrderDecorator filter = filters.get(i); - if (i > 0) { OrderDecorator previous = filters.get(i - 1); if (filter.getOrder() == previous.getOrder()) { @@ -320,29 +299,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { List buildCustomFilterList(Element element, ParserContext pc) { List customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER); List customFilters = new ArrayList<>(); - - final String ATT_AFTER = "after"; - final String ATT_BEFORE = "before"; - final String ATT_POSITION = "position"; - for (Element elt : customFilterElts) { String after = elt.getAttribute(ATT_AFTER); String before = elt.getAttribute(ATT_BEFORE); String position = elt.getAttribute(ATT_POSITION); - String ref = elt.getAttribute(ATT_REF); - if (!StringUtils.hasText(ref)) { pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt)); } - RuntimeBeanReference bean = new RuntimeBeanReference(ref); - if (WebConfigUtils.countNonEmpty(new String[] { after, before, position }) != 1) { pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" + ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt)); } - if (StringUtils.hasText(position)) { customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position))); } @@ -365,7 +334,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } } } - return customFilters; } @@ -379,7 +347,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class); listFactoryBean.getPropertyValues().add("sourceList", new ManagedList()); pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS)); - BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class); fcpBldr.getRawBeanDefinition().setSource(source); fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS); @@ -387,7 +354,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { BeanDefinition fcpBean = fcpBldr.getBeanDefinition(); pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY)); registry.registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); - BeanDefinitionBuilder requestRejected = BeanDefinitionBuilder .rootBeanDefinition(RequestRejectedHandlerPostProcessor.class); requestRejected.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); diff --git a/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java index 07aebdfb3a..65c1b3b931 100644 --- a/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java @@ -44,8 +44,11 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_INVALIDATE_SESSION = "invalidate-session"; static final String ATT_LOGOUT_URL = "logout-url"; + static final String DEF_LOGOUT_URL = "/logout"; + static final String ATT_LOGOUT_HANDLER = "success-handler-ref"; + static final String ATT_DELETE_COOKIES = "delete-cookies"; final String rememberMeServices; @@ -72,9 +75,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { String logoutSuccessUrl = null; String invalidateSession = null; String deleteCookies = null; - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); - if (element != null) { Object source = pc.extractSource(element); builder.getRawBeanDefinition().setSource(source); @@ -86,13 +87,10 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION); deleteCookies = element.getAttribute(ATT_DELETE_COOKIES); } - if (!StringUtils.hasText(logoutUrl)) { logoutUrl = DEF_LOGOUT_URL; } - builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl)); - if (StringUtils.hasText(successHandlerRef)) { if (StringUtils.hasText(logoutSuccessUrl)) { pc.getReaderContext().error( @@ -108,26 +106,20 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { } builder.addConstructorArgValue(logoutSuccessUrl); } - BeanDefinition sclh = new RootBeanDefinition(SecurityContextLogoutHandler.class); sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", !"false".equals(invalidateSession)); this.logoutHandlers.add(sclh); - if (this.rememberMeServices != null) { this.logoutHandlers.add(new RuntimeBeanReference(this.rememberMeServices)); } - if (StringUtils.hasText(deleteCookies)) { BeanDefinition cookieDeleter = new RootBeanDefinition(CookieClearingLogoutHandler.class); String[] names = StringUtils.tokenizeToStringArray(deleteCookies, ","); cookieDeleter.getConstructorArgumentValues().addGenericArgumentValue(names); this.logoutHandlers.add(cookieDeleter); } - this.logoutHandlers.add(new RootBeanDefinition(LogoutSuccessEventPublishingLogoutHandler.class)); - builder.addConstructorArgValue(this.logoutHandlers); - return builder.getBeanDefinition(); } @@ -138,7 +130,6 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { if (this.csrfEnabled) { matcherBuilder.addConstructorArgValue("POST"); } - return matcherBuilder.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/http/MatcherType.java b/config/src/main/java/org/springframework/security/config/http/MatcherType.java index a989ecc8b3..9d65f9ea63 100644 --- a/config/src/main/java/org/springframework/security/config/http/MatcherType.java +++ b/config/src/main/java/org/springframework/security/config/http/MatcherType.java @@ -58,13 +58,10 @@ public enum MatcherType { if (("/**".equals(path) || "**".equals(path)) && method == null) { return new RootBeanDefinition(AnyRequestMatcher.class); } - BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type); - if (this == mvc) { matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class)); } - matcherBldr.addConstructorArgValue(path); if (this == mvc) { matcherBldr.addPropertyValue("method", method); @@ -73,11 +70,9 @@ public enum MatcherType { else { matcherBldr.addConstructorArgValue(method); } - if (this == ciRegex) { matcherBldr.addConstructorArgValue(true); } - return matcherBldr.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java index 9122d28691..3a72f62585 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java @@ -66,7 +66,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext parserContext) { Element authorizationCodeGrantElt = DomUtils.getChildElementByTagName(element, ELT_AUTHORIZATION_CODE_GRANT); - BeanMetadataElement clientRegistrationRepository = OAuth2ClientBeanDefinitionParserUtils .getClientRegistrationRepository(element); BeanMetadataElement authorizedClientRepository = OAuth2ClientBeanDefinitionParserUtils @@ -80,7 +79,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { } BeanMetadataElement authorizationRequestRepository = getAuthorizationRequestRepository( authorizationCodeGrantElt); - BeanDefinitionBuilder authorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class); String authorizationRequestResolverRef = (authorizationCodeGrantElt != null) @@ -94,7 +92,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { this.authorizationRequestRedirectFilter = authorizationRequestRedirectFilterBuilder .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository) .addPropertyValue("requestCache", this.requestCache).getBeanDefinition(); - this.authorizationCodeGrantFilter = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationCodeGrantFilter.class) .addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository) @@ -102,7 +99,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository).getBeanDefinition(); BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(authorizationCodeGrantElt); - this.authorizationCodeAuthenticationProvider = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationCodeAuthenticationProvider.class) .addConstructorArgValue(accessTokenResponseClient).getBeanDefinition(); @@ -111,33 +107,25 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { } private BeanMetadataElement getAuthorizationRequestRepository(Element element) { - BeanMetadataElement authorizationRequestRepository; String authorizationRequestRepositoryRef = (element != null) ? element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF) : null; if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) { - authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef); + return new RuntimeBeanReference(authorizationRequestRepositoryRef); } - else { - authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition( - "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") - .getBeanDefinition(); - } - return authorizationRequestRepository; + return BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") + .getBeanDefinition(); } private BeanMetadataElement getAccessTokenResponseClient(Element element) { - BeanMetadataElement accessTokenResponseClient; String accessTokenResponseClientRef = (element != null) ? element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF) : null; if (!StringUtils.isEmpty(accessTokenResponseClientRef)) { - accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef); + return new RuntimeBeanReference(accessTokenResponseClientRef); } - else { - accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition( - "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") - .getBeanDefinition(); - } - return accessTokenResponseClient; + return BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") + .getBeanDefinition(); } BeanDefinition getDefaultAuthorizedClientRepository() { diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java index 40be5b39aa..8b8a333c7b 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java @@ -41,15 +41,11 @@ final class OAuth2ClientBeanDefinitionParserUtils { } static BeanMetadataElement getClientRegistrationRepository(Element element) { - BeanMetadataElement clientRegistrationRepository; String clientRegistrationRepositoryRef = element.getAttribute(ATT_CLIENT_REGISTRATION_REPOSITORY_REF); if (!StringUtils.isEmpty(clientRegistrationRepositoryRef)) { - clientRegistrationRepository = new RuntimeBeanReference(clientRegistrationRepositoryRef); + return new RuntimeBeanReference(clientRegistrationRepositoryRef); } - else { - clientRegistrationRepository = new RuntimeBeanReference(ClientRegistrationRepository.class); - } - return clientRegistrationRepository; + return new RuntimeBeanReference(ClientRegistrationRepository.class); } static BeanMetadataElement getAuthorizedClientRepository(Element element) { diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java index e83d2a593f..a62cd65055 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java @@ -50,11 +50,9 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg (ListableBeanFactory) this.beanFactory, ClientRegistrationRepository.class, false, false); String[] authorizedClientRepositoryBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( (ListableBeanFactory) this.beanFactory, OAuth2AuthorizedClientRepository.class, false, false); - if (clientRegistrationRepositoryBeanNames.length != 1 || authorizedClientRepositoryBeanNames.length != 1) { return; } - for (String beanName : registry.getBeanDefinitionNames()) { BeanDefinition beanDefinition = registry.getBeanDefinition(beanName); if (RequestMappingHandlerAdapter.class.getName().equals(beanDefinition.getBeanClassName())) { @@ -64,10 +62,8 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg if (currentArgumentResolvers != null) { argumentResolvers.addAll((ManagedList) currentArgumentResolvers.getValue()); } - String[] authorizedClientManagerBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( (ListableBeanFactory) this.beanFactory, OAuth2AuthorizedClientManager.class, false, false); - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder .genericBeanDefinition(OAuth2AuthorizedClientArgumentResolver.class); if (authorizedClientManagerBeanNames.length == 1) { diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java index 673e26fb8c..288b09072e 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java @@ -144,7 +144,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { String oauth2LoginBeanConfigId = parserContext.getReaderContext().generateBeanName(oauth2LoginBeanConfig); parserContext .registerBeanComponent(new BeanComponentDefinition(oauth2LoginBeanConfig, oauth2LoginBeanConfigId)); - // configure filter BeanMetadataElement clientRegistrationRepository = OAuth2ClientBeanDefinitionParserUtils .getClientRegistrationRepository(element); @@ -160,17 +159,14 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(element); BeanMetadataElement oauth2UserService = getOAuth2UserService(element); BeanMetadataElement authorizationRequestRepository = getAuthorizationRequestRepository(element); - BeanDefinitionBuilder oauth2LoginAuthenticationFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2LoginAuthenticationFilter.class) .addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository) .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository); - if (this.sessionStrategy != null) { oauth2LoginAuthenticationFilterBuilder.addPropertyValue("sessionAuthenticationStrategy", this.sessionStrategy); } - Object source = parserContext.extractSource(element); String loginProcessingUrl = element.getAttribute(ATT_LOGIN_PROCESSING_URL); if (!StringUtils.isEmpty(loginProcessingUrl)) { @@ -181,25 +177,19 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { oauth2LoginAuthenticationFilterBuilder .addConstructorArgValue(OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI); } - BeanDefinitionBuilder oauth2LoginAuthenticationProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2LoginAuthenticationProvider.class) .addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oauth2UserService); - String userAuthoritiesMapperRef = element.getAttribute(ATT_USER_AUTHORITIES_MAPPER_REF); if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) { oauth2LoginAuthenticationProviderBuilder.addPropertyReference("authoritiesMapper", userAuthoritiesMapperRef); } - this.oauth2LoginAuthenticationProvider = oauth2LoginAuthenticationProviderBuilder.getBeanDefinition(); - this.oauth2LoginOidcAuthenticationProvider = getOidcAuthProvider(element, accessTokenResponseClient, userAuthoritiesMapperRef); - BeanDefinitionBuilder oauth2AuthorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class); - String authorizationRequestResolverRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_RESOLVER_REF); if (!StringUtils.isEmpty(authorizationRequestResolverRef)) { oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgReference(authorizationRequestResolverRef); @@ -207,13 +197,11 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { else { oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgValue(clientRegistrationRepository); } - oauth2AuthorizationRequestRedirectFilterBuilder .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository) .addPropertyValue("requestCache", this.requestCache); this.oauth2AuthorizationRequestRedirectFilter = oauth2AuthorizationRequestRedirectFilterBuilder .getBeanDefinition(); - String authenticationSuccessHandlerRef = element.getAttribute(ATT_AUTHENTICATION_SUCCESS_HANDLER_REF); if (!StringUtils.isEmpty(authenticationSuccessHandlerRef)) { oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationSuccessHandler", @@ -226,7 +214,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { oauth2LoginAuthenticationFilterBuilder.addPropertyValue("authenticationSuccessHandler", successHandlerBuilder.getBeanDefinition()); } - String loginPage = element.getAttribute(ATT_LOGIN_PAGE); if (!StringUtils.isEmpty(loginPage)) { WebConfigUtils.validateHttpRedirect(loginPage, parserContext, source); @@ -244,7 +231,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { .getBeanDefinition(); } } - String authenticationFailureHandlerRef = element.getAttribute(ATT_AUTHENTICATION_FAILURE_HANDLER_REF); if (!StringUtils.isEmpty(authenticationFailureHandlerRef)) { oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationFailureHandler", @@ -259,95 +245,71 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { oauth2LoginAuthenticationFilterBuilder.addPropertyValue("authenticationFailureHandler", failureHandlerBuilder.getBeanDefinition()); } - // prepare loginlinks this.oauth2LoginLinks = BeanDefinitionBuilder.rootBeanDefinition(Map.class) .setFactoryMethodOnBean("getLoginLinks", oauth2LoginBeanConfigId).getBeanDefinition(); - return oauth2LoginAuthenticationFilterBuilder.getBeanDefinition(); } private BeanMetadataElement getAuthorizationRequestRepository(Element element) { - BeanMetadataElement authorizationRequestRepository; String authorizationRequestRepositoryRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF); if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) { - authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef); + return new RuntimeBeanReference(authorizationRequestRepositoryRef); } - else { - authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition( - "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") - .getBeanDefinition(); - } - return authorizationRequestRepository; + return BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") + .getBeanDefinition(); } private BeanDefinition getOidcAuthProvider(Element element, BeanMetadataElement accessTokenResponseClient, String userAuthoritiesMapperRef) { - boolean oidcAuthenticationProviderEnabled = ClassUtils .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); if (!oidcAuthenticationProviderEnabled) { return BeanDefinitionBuilder.rootBeanDefinition(OidcAuthenticationRequestChecker.class).getBeanDefinition(); } - BeanMetadataElement oidcUserService = getOidcUserService(element); - BeanDefinitionBuilder oidcAuthProviderBuilder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider") .addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oidcUserService); - if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) { oidcAuthProviderBuilder.addPropertyReference("authoritiesMapper", userAuthoritiesMapperRef); } - String jwtDecoderFactoryRef = element.getAttribute(ATT_JWT_DECODER_FACTORY_REF); if (!StringUtils.isEmpty(jwtDecoderFactoryRef)) { oidcAuthProviderBuilder.addPropertyReference("jwtDecoderFactory", jwtDecoderFactoryRef); } - return oidcAuthProviderBuilder.getBeanDefinition(); } private BeanMetadataElement getOidcUserService(Element element) { - BeanMetadataElement oidcUserService; String oidcUserServiceRef = element.getAttribute(ATT_OIDC_USER_SERVICE_REF); if (!StringUtils.isEmpty(oidcUserServiceRef)) { - oidcUserService = new RuntimeBeanReference(oidcUserServiceRef); + return new RuntimeBeanReference(oidcUserServiceRef); } - else { - oidcUserService = BeanDefinitionBuilder - .rootBeanDefinition("org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService") - .getBeanDefinition(); - } - return oidcUserService; + return BeanDefinitionBuilder + .rootBeanDefinition("org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService") + .getBeanDefinition(); } private BeanMetadataElement getOAuth2UserService(Element element) { - BeanMetadataElement oauth2UserService; String oauth2UserServiceRef = element.getAttribute(ATT_USER_SERVICE_REF); if (!StringUtils.isEmpty(oauth2UserServiceRef)) { - oauth2UserService = new RuntimeBeanReference(oauth2UserServiceRef); + return new RuntimeBeanReference(oauth2UserServiceRef); } - else { - oauth2UserService = BeanDefinitionBuilder - .rootBeanDefinition("org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService") - .getBeanDefinition(); - } - return oauth2UserService; + return BeanDefinitionBuilder + .rootBeanDefinition("org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService") + .getBeanDefinition(); } private BeanMetadataElement getAccessTokenResponseClient(Element element) { - BeanMetadataElement accessTokenResponseClient; String accessTokenResponseClientRef = element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF); if (!StringUtils.isEmpty(accessTokenResponseClientRef)) { - accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef); + return new RuntimeBeanReference(accessTokenResponseClientRef); } - else { - accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition( - "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") - .getBeanDefinition(); - } - return accessTokenResponseClient; + return BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") + .getBeanDefinition(); } BeanDefinition getDefaultAuthorizedClientRepository() { @@ -386,10 +348,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(); RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher( new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); - RequestMatcher notXRequestedWith = new NegatedRequestMatcher( new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); - Element clientRegElt = clientRegList.get(0); entryPoints = new LinkedHashMap<>(); entryPoints.put( @@ -417,22 +377,19 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication; - - // Section 3.1.2.1 Authentication Request - - // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest - // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() + if (!authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() .contains(OidcScopes.OPENID)) { - - OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured", - "An OpenID Connect Authentication Provider has not been configured. " - + "Check to ensure you include the dependency 'spring-security-oauth2-jose'.", - null); - throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); + return null; } - - return null; + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest scope + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope + // value. + OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured", + "An OpenID Connect Authentication Provider has not been configured. " + + "Check to ensure you include the dependency 'spring-security-oauth2-jose'.", + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @Override @@ -466,13 +423,11 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { if (clientRegistrations == null) { return Collections.emptyMap(); } - String authorizationRequestBaseUri = DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; Map loginUrlToClientName = new HashMap<>(); clientRegistrations.forEach((registration) -> loginUrlToClientName.put( authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName())); - return loginUrlToClientName; } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java index 7d5d9ba6f0..2be6d13796 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java @@ -62,10 +62,13 @@ import org.springframework.util.xml.DomUtils; final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionParser { static final String AUTHENTICATION_MANAGER_RESOLVER_REF = "authentication-manager-resolver-ref"; + static final String BEARER_TOKEN_RESOLVER_REF = "bearer-token-resolver-ref"; + static final String ENTRY_POINT_REF = "entry-point-ref"; static final String BEARER_TOKEN_RESOLVER = "bearerTokenResolver"; + static final String AUTHENTICATION_ENTRY_POINT = "authenticationEntryPoint"; private final BeanReference authenticationManager; @@ -105,34 +108,27 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa public BeanDefinition parse(Element oauth2ResourceServer, ParserContext pc) { Element jwt = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.JWT); Element opaqueToken = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.OPAQUE_TOKEN); - validateConfiguration(oauth2ResourceServer, jwt, opaqueToken, pc); - if (jwt != null) { BeanDefinition jwtAuthenticationProvider = new JwtBeanDefinitionParser().parse(jwt, pc); this.authenticationProviders.add(new RuntimeBeanReference( pc.getReaderContext().registerWithGeneratedName(jwtAuthenticationProvider))); } - if (opaqueToken != null) { BeanDefinition opaqueTokenAuthenticationProvider = new OpaqueTokenBeanDefinitionParser().parse(opaqueToken, pc); this.authenticationProviders.add(new RuntimeBeanReference( pc.getReaderContext().registerWithGeneratedName(opaqueTokenAuthenticationProvider))); } - BeanMetadataElement bearerTokenResolver = getBearerTokenResolver(oauth2ResourceServer); BeanDefinitionBuilder requestMatcherBuilder = BeanDefinitionBuilder .rootBeanDefinition(BearerTokenRequestMatcher.class); requestMatcherBuilder.addConstructorArgValue(bearerTokenResolver); BeanDefinition requestMatcher = requestMatcherBuilder.getBeanDefinition(); - BeanMetadataElement authenticationEntryPoint = getEntryPoint(oauth2ResourceServer); - this.entryPoints.put(requestMatcher, authenticationEntryPoint); this.deniedHandlers.put(requestMatcher, this.accessDeniedHandler); this.ignoreCsrfRequestMatchers.add(requestMatcher); - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder .rootBeanDefinition(BearerTokenAuthenticationFilter.class); BeanMetadataElement authenticationManagerResolver = getAuthenticationManagerResolver(oauth2ResourceServer); @@ -145,22 +141,19 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa void validateConfiguration(Element oauth2ResourceServer, Element jwt, Element opaqueToken, ParserContext pc) { if (!oauth2ResourceServer.hasAttribute(AUTHENTICATION_MANAGER_RESOLVER_REF)) { if (jwt == null && opaqueToken == null) { - pc.getReaderContext() - .error("Didn't find authentication-manager-resolver-ref, , or . " - + "Please select one.", oauth2ResourceServer); + pc.getReaderContext().error("Didn't find authentication-manager-resolver-ref, " + + ", or . " + "Please select one.", oauth2ResourceServer); } return; } - if (jwt != null) { pc.getReaderContext().error( - "Found as well as authentication-manager-resolver-ref. " + "Please select just one.", + "Found as well as authentication-manager-resolver-ref. Please select just one.", oauth2ResourceServer); } - if (opaqueToken != null) { pc.getReaderContext().error( - "Found as well as authentication-manager-resolver-ref. " + "Please select just one.", + "Found as well as authentication-manager-resolver-ref. Please select just one.", oauth2ResourceServer); } } @@ -181,9 +174,7 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa if (StringUtils.isEmpty(bearerTokenResolverRef)) { return new RootBeanDefinition(DefaultBearerTokenResolver.class); } - else { - return new RuntimeBeanReference(bearerTokenResolverRef); - } + return new RuntimeBeanReference(bearerTokenResolverRef); } BeanMetadataElement getEntryPoint(Element element) { @@ -191,34 +182,35 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa if (StringUtils.isEmpty(entryPointRef)) { return this.authenticationEntryPoint; } - else { - return new RuntimeBeanReference(entryPointRef); - } + return new RuntimeBeanReference(entryPointRef); } static final class JwtBeanDefinitionParser implements BeanDefinitionParser { static final String DECODER_REF = "decoder-ref"; + static final String JWK_SET_URI = "jwk-set-uri"; + static final String JWT_AUTHENTICATION_CONVERTER_REF = "jwt-authentication-converter-ref"; + static final String JWT_AUTHENTICATION_CONVERTER = "jwtAuthenticationConverter"; + JwtBeanDefinitionParser() { + } + @Override public BeanDefinition parse(Element element, ParserContext pc) { validateConfiguration(element, pc); - BeanDefinitionBuilder jwtProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(JwtAuthenticationProvider.class); jwtProviderBuilder.addConstructorArgValue(getDecoder(element)); jwtProviderBuilder.addPropertyValue(JWT_AUTHENTICATION_CONVERTER, getJwtAuthenticationConverter(element)); - return jwtProviderBuilder.getBeanDefinition(); } void validateConfiguration(Element element, ParserContext pc) { boolean usesDecoder = element.hasAttribute(DECODER_REF); boolean usesJwkSetUri = element.hasAttribute(JWK_SET_URI); - if (usesDecoder == usesJwkSetUri) { pc.getReaderContext().error("Please specify either decoder-ref or jwk-set-uri.", element); } @@ -229,7 +221,6 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa if (!StringUtils.isEmpty(decoderRef)) { return new RuntimeBeanReference(decoderRef); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder .rootBeanDefinition(NimbusJwtDecoderJwkSetUriFactoryBean.class); builder.addConstructorArgValue(element.getAttribute(JWK_SET_URI)); @@ -238,14 +229,8 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa Object getJwtAuthenticationConverter(Element element) { String jwtDecoderRef = element.getAttribute(JWT_AUTHENTICATION_CONVERTER_REF); - if (!StringUtils.isEmpty(jwtDecoderRef)) { - return new RuntimeBeanReference(jwtDecoderRef); - } - - return new JwtAuthenticationConverter(); - } - - JwtBeanDefinitionParser() { + return (!StringUtils.isEmpty(jwtDecoderRef)) ? new RuntimeBeanReference(jwtDecoderRef) + : new JwtAuthenticationConverter(); } } @@ -253,19 +238,23 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa static final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser { static final String INTROSPECTOR_REF = "introspector-ref"; + static final String INTROSPECTION_URI = "introspection-uri"; + static final String CLIENT_ID = "client-id"; + static final String CLIENT_SECRET = "client-secret"; + OpaqueTokenBeanDefinitionParser() { + } + @Override public BeanDefinition parse(Element element, ParserContext pc) { validateConfiguration(element, pc); - BeanMetadataElement introspector = getIntrospector(element); BeanDefinitionBuilder opaqueTokenProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(OpaqueTokenAuthenticationProvider.class); opaqueTokenProviderBuilder.addConstructorArgValue(introspector); - return opaqueTokenProviderBuilder.getBeanDefinition(); } @@ -273,13 +262,11 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa boolean usesIntrospector = element.hasAttribute(INTROSPECTOR_REF); boolean usesEndpoint = element.hasAttribute(INTROSPECTION_URI) || element.hasAttribute(CLIENT_ID) || element.hasAttribute(CLIENT_SECRET); - if (usesIntrospector == usesEndpoint) { pc.getReaderContext().error("Please specify either introspector-ref or all of " + "introspection-uri, client-id, and client-secret.", element); return; } - if (usesEndpoint) { if (!(element.hasAttribute(INTROSPECTION_URI) && element.hasAttribute(CLIENT_ID) && element.hasAttribute(CLIENT_SECRET))) { @@ -294,23 +281,17 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa if (!StringUtils.isEmpty(introspectorRef)) { return new RuntimeBeanReference(introspectorRef); } - String introspectionUri = element.getAttribute(INTROSPECTION_URI); String clientId = element.getAttribute(CLIENT_ID); String clientSecret = element.getAttribute(CLIENT_SECRET); - BeanDefinitionBuilder introspectorBuilder = BeanDefinitionBuilder .rootBeanDefinition(NimbusOpaqueTokenIntrospector.class); introspectorBuilder.addConstructorArgValue(introspectionUri); introspectorBuilder.addConstructorArgValue(clientId); introspectorBuilder.addConstructorArgValue(clientSecret); - return introspectorBuilder.getBeanDefinition(); } - OpaqueTokenBeanDefinitionParser() { - } - } static final class StaticAuthenticationManagerResolver diff --git a/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java index e6a844a196..dff5ebfa5b 100644 --- a/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java @@ -48,33 +48,25 @@ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition portMapper = new RootBeanDefinition(PortMapperImpl.class); portMapper.setSource(parserContext.extractSource(element)); - if (element != null) { List mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING); if (mappingElts.isEmpty()) { parserContext.getReaderContext().error("No port-mapping child elements specified", element); } - Map mappings = new ManagedMap(); - for (Element elt : mappingElts) { String httpPort = elt.getAttribute(ATT_HTTP_PORT); String httpsPort = elt.getAttribute(ATT_HTTPS_PORT); - if (!StringUtils.hasText(httpPort)) { parserContext.getReaderContext().error("No http port supplied in port mapping", elt); } - if (!StringUtils.hasText(httpsPort)) { parserContext.getReaderContext().error("No https port supplied in port mapping", elt); } - mappings.put(httpPort, httpsPort); } - portMapper.getPropertyValues().addPropertyValue("portMappings", mappings); } - return portMapper; } diff --git a/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java index 97bcaa1bda..85ac360cf6 100644 --- a/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java @@ -45,14 +45,23 @@ import org.springframework.util.StringUtils; class RememberMeBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_DATA_SOURCE = "data-source-ref"; + static final String ATT_SERVICES_REF = "services-ref"; + static final String ATT_SERVICES_ALIAS = "services-alias"; + static final String ATT_TOKEN_REPOSITORY = "token-repository-ref"; + static final String ATT_USER_SERVICE_REF = "user-service-ref"; + static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref"; + static final String ATT_TOKEN_VALIDITY = "token-validity-seconds"; + static final String ATT_SECURE_COOKIE = "use-secure-cookie"; + static final String ATT_FORM_REMEMBERME_PARAMETER = "remember-me-parameter"; + static final String ATT_REMEMBERME_COOKIE = "remember-me-cookie"; protected final Log logger = LogFactory.getLog(getClass()); @@ -73,7 +82,6 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)); pc.pushContainingComponent(compositeDef); - String tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY); String dataSource = element.getAttribute(ATT_DATA_SOURCE); String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF); @@ -84,9 +92,7 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { String remembermeParameter = element.getAttribute(ATT_FORM_REMEMBERME_PARAMETER); String remembermeCookie = element.getAttribute(ATT_REMEMBERME_COOKIE); Object source = pc.extractSource(element); - RootBeanDefinition services = null; - boolean dataSourceSet = StringUtils.hasText(dataSource); boolean tokenRepoSet = StringUtils.hasText(tokenRepository); boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef); @@ -95,7 +101,6 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds); boolean remembermeParameterSet = StringUtils.hasText(remembermeParameter); boolean remembermeCookieSet = StringUtils.hasText(remembermeCookie); - if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet || useSecureCookieSet || remembermeParameterSet || remembermeCookieSet)) { pc.getReaderContext() @@ -104,18 +109,14 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { + ATT_SECURE_COOKIE + ", " + ATT_FORM_REMEMBERME_PARAMETER + " or " + ATT_REMEMBERME_COOKIE, source); } - if (dataSourceSet && tokenRepoSet) { pc.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + ATT_DATA_SOURCE + " but not both", source); } - boolean isPersistent = dataSourceSet | tokenRepoSet; - if (isPersistent) { Object tokenRepo; services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class); - if (tokenRepoSet) { tokenRepo = new RuntimeBeanReference(tokenRepository); } @@ -129,24 +130,19 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { else if (!servicesRefSet) { services = new RootBeanDefinition(TokenBasedRememberMeServices.class); } - String servicesName; - if (services != null) { RootBeanDefinition uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("cachingUserDetailsService"); uds.getConstructorArgumentValues().addGenericArgumentValue(userServiceRef); - services.getConstructorArgumentValues().addGenericArgumentValue(this.key); services.getConstructorArgumentValues().addGenericArgumentValue(uds); // tokenRepo is already added if it is a // PersistentTokenBasedRememberMeServices - if (useSecureCookieSet) { services.getPropertyValues().addPropertyValue("useSecureCookie", Boolean.valueOf(useSecureCookie)); } - if (tokenValiditySet) { boolean isTokenValidityNegative = tokenValiditySeconds.startsWith("-"); if (isTokenValidityNegative && isPersistent) { @@ -155,15 +151,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { } services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValiditySeconds); } - if (remembermeParameterSet) { services.getPropertyValues().addPropertyValue("parameter", remembermeParameter); } - if (remembermeCookieSet) { services.getPropertyValues().addPropertyValue("cookieName", remembermeCookie); } - services.setSource(source); servicesName = pc.getReaderContext().generateBeanName(services); pc.registerBeanComponent(new BeanComponentDefinition(services, servicesName)); @@ -171,25 +164,18 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { else { servicesName = rememberMeServicesRef; } - if (StringUtils.hasText(element.getAttribute(ATT_SERVICES_ALIAS))) { pc.getRegistry().registerAlias(servicesName, element.getAttribute(ATT_SERVICES_ALIAS)); } - this.rememberMeServicesId = servicesName; - BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(RememberMeAuthenticationFilter.class); filter.getRawBeanDefinition().setSource(source); - if (StringUtils.hasText(successHandlerRef)) { filter.addPropertyReference("authenticationSuccessHandler", successHandlerRef); } - filter.addConstructorArgValue(this.authenticationManager); filter.addConstructorArgReference(servicesName); - pc.popAndRegisterContainingComponent(); - return filter.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java b/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java index 5b67d82ba1..74beef711d 100644 --- a/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java +++ b/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java @@ -28,15 +28,22 @@ import org.springframework.security.core.context.SecurityContext; */ public enum SessionCreationPolicy { - /** Always create an {@link HttpSession} */ + /** + * Always create an {@link HttpSession} + */ ALWAYS, + /** * Spring Security will never create an {@link HttpSession}, but will use the * {@link HttpSession} if it already exists */ NEVER, - /** Spring Security will only create an {@link HttpSession} if required */ + + /** + * Spring Security will only create an {@link HttpSession} if required + */ IF_REQUIRED, + /** * Spring Security will never create an {@link HttpSession} and it will never use it * to obtain the {@link SecurityContext} diff --git a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java index 48000087d1..851416c3f8 100644 --- a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java @@ -46,7 +46,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { if (!StringUtils.hasText(id)) { return getUserDetailsService(); } - return (UserDetailsService) this.beanFactory.getBean(id); } @@ -56,21 +55,17 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { } // Overwrite with the caching version if available String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX; - if (this.beanFactory.containsBeanDefinition(cachingId)) { return (UserDetailsService) this.beanFactory.getBean(cachingId); } - return (UserDetailsService) this.beanFactory.getBean(id); } @SuppressWarnings("unchecked") AuthenticationUserDetailsService authenticationUserDetailsService(String name) { UserDetailsService uds; - if (!StringUtils.hasText(name)) { Map beans = getBeansOfType(AuthenticationUserDetailsService.class); - if (!beans.isEmpty()) { if (beans.size() > 1) { throw new ApplicationContextException("More than one AuthenticationUserDetailsService registered." @@ -78,18 +73,15 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { } return (AuthenticationUserDetailsService) beans.values().toArray()[0]; } - uds = getUserDetailsService(); } else { Object bean = this.beanFactory.getBean(name); - if (bean instanceof AuthenticationUserDetailsService) { return (AuthenticationUserDetailsService) bean; } else if (bean instanceof UserDetailsService) { uds = cachingUserDetailsService(name); - if (uds == null) { uds = (UserDetailsService) bean; } @@ -99,7 +91,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { "Bean '" + name + "' must be a UserDetailsService or an" + " AuthenticationUserDetailsService"); } } - return new UserDetailsByNameServiceWrapper(uds); } @@ -110,20 +101,16 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { */ private UserDetailsService getUserDetailsService() { Map beans = getBeansOfType(CachingUserDetailsService.class); - if (beans.size() == 0) { beans = getBeansOfType(UserDetailsService.class); } - if (beans.size() == 0) { throw new ApplicationContextException("No UserDetailsService registered."); - } - else if (beans.size() > 1) { + if (beans.size() > 1) { throw new ApplicationContextException("More than one UserDetailsService registered. Please " + "use a specific Id reference in or elements."); } - return (UserDetailsService) beans.values().toArray()[0]; } @@ -134,7 +121,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { private Map getBeansOfType(Class type) { Map beans = this.beanFactory.getBeansOfType(type); - // Check ancestor bean factories if they exist and the current one has none of the // required type BeanFactory parent = this.beanFactory.getParentBeanFactory(); @@ -149,7 +135,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { break; } } - return beans; } diff --git a/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java b/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java index b97dd909a1..1a7b5e72b7 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java @@ -50,37 +50,34 @@ public class ContextSourceSettingPostProcessor implements BeanFactoryPostProcess @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException { - Class contextSourceClass; - - try { - contextSourceClass = ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME, - ClassUtils.getDefaultClassLoader()); - } - catch (ClassNotFoundException ex) { - throw new ApplicationContextException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". " - + " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap " - + "jar file in your application", ex); - } - + Class contextSourceClass = getContextSourceClass(); String[] sources = bf.getBeanNamesForType(contextSourceClass, false, false); - if (sources.length == 0) { throw new ApplicationContextException("No BaseLdapPathContextSource instances found. Have you " + "added an <" + Elements.LDAP_SERVER + " /> element to your application context? If you have " + "declared an explicit bean, do not use lazy-init"); } - if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && this.defaultNameRequired) { if (sources.length > 1) { throw new ApplicationContextException("More than one BaseLdapPathContextSource instance found. " + "Please specify a specific server id using the 'server-ref' attribute when configuring your <" + Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">."); } - bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE); } } + private Class getContextSourceClass() throws LinkageError { + try { + return ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME, ClassUtils.getDefaultClassLoader()); + } + catch (ClassNotFoundException ex) { + throw new ApplicationContextException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". " + + " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap " + + "jar file in your application", ex); + } + } + public void setDefaultNameRequired(boolean defaultNameRequired) { this.defaultNameRequired = defaultNameRequired; } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java index 201ac0aa7f..3e735458f4 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java @@ -49,19 +49,18 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { private static final String DEF_USER_SEARCH_FILTER = "uid={0}"; static final String PROVIDER_CLASS = "org.springframework.security.ldap.authentication.LdapAuthenticationProvider"; + static final String BIND_AUTH_CLASS = "org.springframework.security.ldap.authentication.BindAuthenticator"; + static final String PASSWD_AUTH_CLASS = "org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator"; @Override public BeanDefinition parse(Element elt, ParserContext parserContext) { RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, parserContext); - BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext); String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN); - String[] userDnPatternArray = new String[0]; - if (StringUtils.hasText(userDnPattern)) { userDnPatternArray = new String[] { userDnPattern }; // TODO: Validate the pattern and make sure it is a valid DN. @@ -77,22 +76,17 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { searchBeanBuilder.addConstructorArgValue(contextSource); searchBean = searchBeanBuilder.getBeanDefinition(); } - BeanDefinitionBuilder authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS); Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE); - if (passwordCompareElt != null) { authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS); - String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD); if (StringUtils.hasText(passwordAttribute)) { authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute); } - Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER); String hash = passwordCompareElt.getAttribute(ATT_HASH); - if (passwordEncoderElement != null) { if (StringUtils.hasText(hash)) { parserContext.getReaderContext().warning( @@ -107,21 +101,17 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { PasswordEncoderParser.createPasswordEncoderBeanDefinition(hash, false)); } } - authenticatorBuilder.addConstructorArgValue(contextSource); authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray); - if (searchBean != null) { authenticatorBuilder.addPropertyValue("userSearch", searchBean); } - BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS); ldapProvider.addConstructorArgValue(authenticatorBuilder.getBeanDefinition()); ldapProvider.addConstructorArgValue( LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); ldapProvider.addPropertyValue("userDetailsContextMapper", LdapUserServiceBeanDefinitionParser.parseUserDetailsClassOrUserMapperRef(elt, parserContext)); - return ldapProvider.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index 40526d31e6..3da012c375 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java @@ -89,9 +89,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element elt, ParserContext parserContext) { String url = elt.getAttribute(ATT_URL); - RootBeanDefinition contextSource; - if (!StringUtils.hasText(url)) { contextSource = createEmbeddedServer(elt, parserContext); } @@ -100,28 +98,20 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS); contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url); } - contextSource.setSource(parserContext.extractSource(elt)); - String managerDn = elt.getAttribute(ATT_PRINCIPAL); String managerPassword = elt.getAttribute(ATT_PASSWORD); - if (StringUtils.hasText(managerDn)) { if (!StringUtils.hasText(managerPassword)) { parserContext.getReaderContext() .error("You must specify the " + ATT_PASSWORD + " if you supply a " + managerDn, elt); } - contextSource.getPropertyValues().addPropertyValue("userDn", managerDn); contextSource.getPropertyValues().addPropertyValue("password", managerPassword); } - String id = elt.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE); - String contextSourceId = StringUtils.hasText(id) ? id : BeanIds.CONTEXT_SOURCE; - parserContext.getRegistry().registerBeanDefinition(contextSourceId, contextSource); - return null; } @@ -136,52 +126,40 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { */ private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); - String suffix = element.getAttribute(ATT_ROOT_SUFFIX); - if (!StringUtils.hasText(suffix)) { suffix = OPT_DEFAULT_ROOT_SUFFIX; } - BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS); contextSource.addConstructorArgValue(suffix); contextSource.addPropertyValue("userDn", "uid=admin,ou=system"); contextSource.addPropertyValue("password", "secret"); - BeanDefinition embeddedLdapServerConfigBean = BeanDefinitionBuilder .rootBeanDefinition(EmbeddedLdapServerConfigBean.class).getBeanDefinition(); String embeddedLdapServerConfigBeanName = parserContext.getReaderContext() .generateBeanName(embeddedLdapServerConfigBean); - parserContext.registerBeanComponent( new BeanComponentDefinition(embeddedLdapServerConfigBean, embeddedLdapServerConfigBeanName)); - contextSource.setFactoryMethodOnBean("createEmbeddedContextSource", embeddedLdapServerConfigBeanName); - String mode = element.getAttribute("mode"); RootBeanDefinition ldapContainer = getRootBeanDefinition(mode); ldapContainer.setSource(source); ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix); - String ldifs = element.getAttribute(ATT_LDIF_FILE); if (!StringUtils.hasText(ldifs)) { ldifs = OPT_DEFAULT_LDIF_FILE; } - ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs); ldapContainer.getPropertyValues().addPropertyValue("port", getPort(element)); - if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS) || parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) { parserContext.getReaderContext().error("Only one embedded server bean is allowed per application context", element); } - String beanId = resolveBeanId(mode); if (beanId != null) { parserContext.getRegistry().registerBeanDefinition(beanId, ldapContainer); } - return (RootBeanDefinition) contextSource.getBeanDefinition(); } @@ -189,7 +167,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { if (isApacheDsEnabled(mode)) { return new RootBeanDefinition(APACHEDS_CONTAINER_CLASSNAME, null, null); } - else if (isUnboundidEnabled(mode)) { + if (isUnboundidEnabled(mode)) { return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null); } throw new IllegalStateException("Embedded LDAP server is not provided"); @@ -199,7 +177,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { if (isApacheDsEnabled(mode)) { return BeanIds.EMBEDDED_APACHE_DS; } - else if (isUnboundidEnabled(mode)) { + if (isUnboundidEnabled(mode)) { return BeanIds.EMBEDDED_UNBOUNDID; } return null; @@ -238,22 +216,21 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unused") private DefaultSpringSecurityContextSource createEmbeddedContextSource(String suffix) { - int port; + int port = getPort(); + String providerUrl = "ldap://127.0.0.1:" + port + "/" + suffix; + return new DefaultSpringSecurityContextSource(providerUrl); + } + + private int getPort() { if (ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader())) { ApacheDSContainer apacheDSContainer = this.applicationContext.getBean(ApacheDSContainer.class); - port = apacheDSContainer.getLocalPort(); + return apacheDSContainer.getLocalPort(); } - else if (ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader())) { + if (ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader())) { UnboundIdContainer unboundIdContainer = this.applicationContext.getBean(UnboundIdContainer.class); - port = unboundIdContainer.getPort(); + return unboundIdContainer.getPort(); } - else { - throw new IllegalStateException("Embedded LDAP server is not provided"); - } - - String providerUrl = "ldap://127.0.0.1:" + port + "/" + suffix; - - return new DefaultSpringSecurityContextSource(providerUrl); + throw new IllegalStateException("Embedded LDAP server is not provided"); } } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java index aa00b4b019..dec9a6ac41 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java @@ -54,9 +54,13 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ public static final String DEF_GROUP_SEARCH_BASE = ""; static final String ATT_ROLE_PREFIX = "role-prefix"; + static final String ATT_USER_CLASS = "user-details-class"; + static final String ATT_USER_CONTEXT_MAPPER_REF = "user-context-mapper-ref"; + static final String OPT_PERSON = "person"; + static final String OPT_INETORGPERSON = "inetOrgPerson"; public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch"; @@ -76,11 +80,9 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ @Override protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) { - if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) { parserContext.getReaderContext().error("User search filter must be supplied", elt); } - builder.addConstructorArgValue(parseSearchBean(elt, parserContext)); builder.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); builder.addConstructorArgValue(parseAuthoritiesPopulator(elt, parserContext)); @@ -91,7 +93,6 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER); String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE); Object source = parserContext.extractSource(elt); - if (StringUtils.hasText(userSearchBase)) { if (!StringUtils.hasText(userSearchFilter)) { parserContext.getReaderContext() @@ -101,33 +102,27 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ else { userSearchBase = DEF_USER_SEARCH_BASE; } - if (!StringUtils.hasText(userSearchFilter)) { return null; } - BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS); searchBuilder.getRawBeanDefinition().setSource(source); searchBuilder.addConstructorArgValue(userSearchBase); searchBuilder.addConstructorArgValue(userSearchFilter); searchBuilder.addConstructorArgValue(parseServerReference(elt, parserContext)); - return (RootBeanDefinition) searchBuilder.getBeanDefinition(); } static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) { String server = elt.getAttribute(ATT_SERVER); boolean requiresDefaultName = false; - if (!StringUtils.hasText(server)) { server = BeanIds.CONTEXT_SOURCE; requiresDefaultName = true; } - RuntimeBeanReference contextSource = new RuntimeBeanReference(server); contextSource.setSource(parserContext.extractSource(elt)); registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName); - return contextSource; } @@ -139,7 +134,6 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ } return; } - BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceSettingPostProcessor.class); bdb.addPropertyValue("defaultNameRequired", defaultNameRequired); registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bdb.getBeanDefinition()); @@ -148,65 +142,54 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ static BeanMetadataElement parseUserDetailsClassOrUserMapperRef(Element elt, ParserContext parserContext) { String userDetailsClass = elt.getAttribute(ATT_USER_CLASS); String userMapperRef = elt.getAttribute(ATT_USER_CONTEXT_MAPPER_REF); - if (StringUtils.hasText(userDetailsClass) && StringUtils.hasText(userMapperRef)) { parserContext.getReaderContext().error("Attributes " + ATT_USER_CLASS + " and " + ATT_USER_CONTEXT_MAPPER_REF + " cannot be used together.", parserContext.extractSource(elt)); } - if (StringUtils.hasText(userMapperRef)) { return new RuntimeBeanReference(userMapperRef); } - - RootBeanDefinition mapper; - - if (OPT_PERSON.equals(userDetailsClass)) { - mapper = new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null); - } - else if (OPT_INETORGPERSON.equals(userDetailsClass)) { - mapper = new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null); - } - else { - mapper = new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null); - } - + RootBeanDefinition mapper = getMapper(userDetailsClass); mapper.setSource(parserContext.extractSource(elt)); - return mapper; } + private static RootBeanDefinition getMapper(String userDetailsClass) { + if (OPT_PERSON.equals(userDetailsClass)) { + return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null); + } + if (OPT_INETORGPERSON.equals(userDetailsClass)) { + return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null); + } + return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null); + } + static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) { String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER); String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE); String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE); String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX); - if (!StringUtils.hasText(groupSearchFilter)) { groupSearchFilter = DEF_GROUP_SEARCH_FILTER; } - if (!StringUtils.hasText(groupSearchBase)) { groupSearchBase = DEF_GROUP_SEARCH_BASE; } - BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS); populator.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); populator.addConstructorArgValue(parseServerReference(elt, parserContext)); populator.addConstructorArgValue(groupSearchBase); populator.addPropertyValue("groupSearchFilter", groupSearchFilter); populator.addPropertyValue("searchSubtree", Boolean.TRUE); - if (StringUtils.hasText(rolePrefix)) { if ("none".equals(rolePrefix)) { rolePrefix = ""; } populator.addPropertyValue("rolePrefix", rolePrefix); } - if (StringUtils.hasLength(groupRoleAttribute)) { populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute); } - return (RootBeanDefinition) populator.getBeanDefinition(); } 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 fde8ab1571..c87b32e169 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 @@ -48,6 +48,7 @@ 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.core.log.LogMessage; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; @@ -122,36 +123,28 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)); pc.pushContainingComponent(compositeDef); - Object source = pc.extractSource(element); // The list of method metadata delegates ManagedList delegates = new ManagedList<>(); - boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250)); boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED)); boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST)); boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE)); - BeanDefinition preInvocationVoter = null; ManagedList afterInvocationProviders = new ManagedList<>(); - // Check for an external SecurityMetadataSource, which takes priority over other // sources String metaDataSourceId = element.getAttribute(ATT_META_DATA_SOURCE_REF); - if (StringUtils.hasText(metaDataSourceId)) { delegates.add(new RuntimeBeanReference(metaDataSourceId)); } - if (prePostAnnotationsEnabled) { Element prePostElt = DomUtils.getChildElementByTagName(element, Elements.INVOCATION_HANDLING); Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER); - if (prePostElt != null && expressionHandlerElt != null) { pc.getReaderContext().error(Elements.INVOCATION_HANDLING + " and " + Elements.EXPRESSION_HANDLER + " cannot be used together ", source); } - BeanDefinitionBuilder preInvocationVoterBldr = BeanDefinitionBuilder .rootBeanDefinition(PreInvocationAuthorizationAdviceVoter.class); // After-invocation provider to handle post-invocation filtering and @@ -161,7 +154,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP // The metadata source for the security interceptor BeanDefinitionBuilder mds = BeanDefinitionBuilder .rootBeanDefinition(PrePostAnnotationSecurityMetadataSource.class); - if (prePostElt != null) { // Customized override of expression handling system String attributeFactoryRef = DomUtils @@ -171,7 +163,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP .getAttribute("ref"); String postAdviceRef = DomUtils.getChildElementByTagName(prePostElt, Elements.POST_INVOCATION_ADVICE) .getAttribute("ref"); - mds.addConstructorArgReference(attributeFactoryRef); preInvocationVoterBldr.addConstructorArgReference(preAdviceRef); afterInvocationBldr.addConstructorArgReference(postAdviceRef); @@ -180,80 +171,65 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP // The default expression-based system String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref") : null; - if (StringUtils.hasText(expressionHandlerRef)) { - this.logger.info( - "Using bean '" + expressionHandlerRef + "' as method ExpressionHandler implementation"); + this.logger.info(LogMessage.format("Using bean '%s' as method ExpressionHandler implementation", + expressionHandlerRef)); RootBeanDefinition lazyInitPP = new RootBeanDefinition( LazyInitBeanDefinitionRegistryPostProcessor.class); lazyInitPP.getConstructorArgumentValues().addGenericArgumentValue(expressionHandlerRef); pc.getReaderContext().registerWithGeneratedName(lazyInitPP); - BeanDefinitionBuilder lazyMethodSecurityExpressionHandlerBldr = BeanDefinitionBuilder .rootBeanDefinition(LazyInitTargetSource.class); lazyMethodSecurityExpressionHandlerBldr.addPropertyValue("targetBeanName", expressionHandlerRef); - BeanDefinitionBuilder expressionHandlerProxyBldr = BeanDefinitionBuilder .rootBeanDefinition(ProxyFactoryBean.class); expressionHandlerProxyBldr.addPropertyValue("targetSource", lazyMethodSecurityExpressionHandlerBldr.getBeanDefinition()); expressionHandlerProxyBldr.addPropertyValue("proxyInterfaces", MethodSecurityExpressionHandler.class); - expressionHandlerRef = pc.getReaderContext() .generateBeanName(expressionHandlerProxyBldr.getBeanDefinition()); - pc.registerBeanComponent(new BeanComponentDefinition(expressionHandlerProxyBldr.getBeanDefinition(), expressionHandlerRef)); } else { RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc, DefaultMethodSecurityExpressionHandlerBeanFactory.class); - expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler); pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef)); - this.logger.info( - "Expressions were enabled for method security but no SecurityExpressionHandler was configured. " - + "All hasPermission() expressions will evaluate to false."); + this.logger.info("Expressions were enabled for method security but no SecurityExpressionHandler " + + "was configured. All hasPermission() expressions will evaluate to false."); } - BeanDefinitionBuilder expressionPreAdviceBldr = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedPreInvocationAdvice.class); expressionPreAdviceBldr.addPropertyReference("expressionHandler", expressionHandlerRef); preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr.getBeanDefinition()); - BeanDefinitionBuilder expressionPostAdviceBldr = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedPostInvocationAdvice.class); expressionPostAdviceBldr.addConstructorArgReference(expressionHandlerRef); afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr.getBeanDefinition()); - BeanDefinitionBuilder annotationInvocationFactory = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedAnnotationAttributeFactory.class); annotationInvocationFactory.addConstructorArgReference(expressionHandlerRef); mds.addConstructorArgValue(annotationInvocationFactory.getBeanDefinition()); } - preInvocationVoter = preInvocationVoterBldr.getBeanDefinition(); afterInvocationProviders.add(afterInvocationBldr.getBeanDefinition()); delegates.add(mds.getBeanDefinition()); } - if (useSecured) { delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SecuredAnnotationSecurityMetadataSource.class) .getBeanDefinition()); } - if (jsr250Enabled) { RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc, Jsr250MethodSecurityMetadataSourceBeanFactory.class); delegates.add(jsrMetadataSource); } - // Now create a Map for each // sub-element Map> pointcutMap = parseProtectPointcuts(pc, DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT)); - if (pointcutMap.size() > 0) { if (useAspectJ) { pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source); @@ -262,34 +238,25 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); BeanReference ref = new RuntimeBeanReference( pc.getReaderContext().generateBeanName(mapBasedMetadataSource)); - delegates.add(ref); pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, ref.getBeanName())); registerProtectPointcutPostProcessor(pc, pointcutMap, ref, source); } - BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, delegates, source); - // Check for additional after-invocation-providers.. List afterInvocationElts = DomUtils.getChildElementsByTagName(element, Elements.AFTER_INVOCATION_PROVIDER); - for (Element elt : afterInvocationElts) { afterInvocationProviders.add(new RuntimeBeanReference(elt.getAttribute(ATT_REF))); } - String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); - if (!StringUtils.hasText(accessManagerId)) { accessManagerId = registerAccessManager(pc, jsr250Enabled, preInvocationVoter); } - String authMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF); - String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR); BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, accessManagerId, runAsManagerId, metadataSource, afterInvocationProviders, source, useAspectJ); - if (useAspectJ) { BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); @@ -303,9 +270,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER)); AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element); } - pc.popAndRegisterContainingComponent(); - return null; } @@ -316,26 +281,20 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP */ @SuppressWarnings({ "unchecked", "rawtypes" }) private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, BeanDefinition expressionVoter) { - BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); ManagedList voters = new ManagedList(4); - if (expressionVoter != null) { voters.add(expressionVoter); } voters.add(new RootBeanDefinition(RoleVoter.class)); voters.add(new RootBeanDefinition(AuthenticatedVoter.class)); - if (jsr250Enabled) { voters.add(new RootBeanDefinition(Jsr250Voter.class)); } - accessMgrBuilder.addConstructorArgValue(voters); - BeanDefinition accessManager = accessMgrBuilder.getBeanDefinition(); String id = pc.getReaderContext().generateBeanName(accessManager); pc.registerBeanComponent(new BeanComponentDefinition(accessManager, id)); - return id; } @@ -346,7 +305,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP DelegatingMethodSecurityMetadataSource.class); delegatingMethodSecurityMetadataSource.setSource(source); delegatingMethodSecurityMetadataSource.getConstructorArgumentValues().addGenericArgumentValue(delegates); - String id = pc.getReaderContext().generateBeanName(delegatingMethodSecurityMetadataSource); pc.registerBeanComponent(new BeanComponentDefinition(delegatingMethodSecurityMetadataSource, id)); @@ -367,31 +325,24 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP private Map> parseProtectPointcuts(ParserContext parserContext, List protectPointcutElts) { Map> pointcutMap = new LinkedHashMap<>(); - for (Element childElt : protectPointcutElts) { String accessConfig = childElt.getAttribute(ATT_ACCESS); String expression = childElt.getAttribute(ATT_EXPRESSION); - if (!StringUtils.hasText(accessConfig)) { parserContext.getReaderContext().error("Access configuration required", parserContext.extractSource(childElt)); } - if (!StringUtils.hasText(expression)) { parserContext.getReaderContext().error("Pointcut expression required", parserContext.extractSource(childElt)); } - String[] attributeTokens = StringUtils.commaDelimitedListToStringArray(accessConfig); List attributes = new ArrayList<>(attributeTokens.length); - for (String token : attributeTokens) { attributes.add(new SecurityConfig(token)); } - pointcutMap.put(expression, attributes); } - return pointcutMap; } @@ -406,22 +357,18 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP authMgr.getConstructorArgumentValues().addGenericArgumentValue(authMgrRef); bldr.addPropertyValue("authenticationManager", authMgr); bldr.addPropertyValue("securityMetadataSource", metadataSource); - if (StringUtils.hasText(runAsManagerId)) { bldr.addPropertyReference("runAsManager", runAsManagerId); } - if (!afterInvocationProviders.isEmpty()) { BeanDefinition afterInvocationManager; afterInvocationManager = new RootBeanDefinition(AfterInvocationProviderManager.class); afterInvocationManager.getPropertyValues().addPropertyValue("providers", afterInvocationProviders); bldr.addPropertyValue("afterInvocationManager", afterInvocationManager); } - BeanDefinition bean = bldr.getBeanDefinition(); String id = pc.getReaderContext().generateBeanName(bean); pc.registerBeanComponent(new BeanComponentDefinition(bean, id)); - return new RuntimeBeanReference(id); } @@ -431,11 +378,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP parserContext.getReaderContext().error("Duplicate detected.", source); } RootBeanDefinition advisor = new RootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); - if (StringUtils.hasText(adviceOrder)) { advisor.getPropertyValues().addPropertyValue("order", adviceOrder); } - // advisor must be an infrastructure bean as Spring's // InfrastructureAdvisorAutoProxyCreator will ignore it // otherwise @@ -444,7 +389,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor.getBeanName()); advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource); advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource.getBeanName()); - parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor); } @@ -453,7 +397,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP 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"); @@ -499,7 +442,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } } } - return this.delegate.authenticate(authentication); } diff --git a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java index 3d6cb881a6..ca4a87b477 100644 --- a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java +++ b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java @@ -52,7 +52,6 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe @Override public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext); - return this.delegate.decorate(node, definition, parserContext); } @@ -64,6 +63,7 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe extends AbstractInterceptorDrivenBeanDefinitionDecorator { static final String ATT_METHOD = "method"; + static final String ATT_ACCESS = "access"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; @@ -73,49 +73,36 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe Element interceptMethodsElt = (Element) node; BeanDefinitionBuilder interceptor = BeanDefinitionBuilder .rootBeanDefinition(MethodSecurityInterceptor.class); - // Default to autowiring to pick up after invocation mgr interceptor.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR); - if (!StringUtils.hasText(accessManagerId)) { accessManagerId = BeanIds.METHOD_ACCESS_MANAGER; } - interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId)); interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); - // Lookup parent bean information - String parentBeanClass = ((Element) node.getParentNode()).getAttribute("class"); - // Parse the included methods List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); Map mappings = new ManagedMap<>(); - for (Element protectmethodElt : methods) { BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString"); attributeBuilder.addConstructorArgValue(protectmethodElt.getAttribute(ATT_ACCESS)); - // Support inference of class names String methodName = protectmethodElt.getAttribute(ATT_METHOD); - if (methodName.lastIndexOf(".") == -1) { if (parentBeanClass != null && !"".equals(parentBeanClass)) { methodName = parentBeanClass + "." + methodName; } } - mappings.put(methodName, attributeBuilder.getBeanDefinition()); } - BeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); interceptor.addPropertyValue("securityMetadataSource", metadataSource); - return interceptor.getBeanDefinition(); } diff --git a/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java b/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java index eb21d3b94c..f951d01446 100644 --- a/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java +++ b/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java @@ -46,11 +46,9 @@ abstract class MethodConfigUtils { @SuppressWarnings("unchecked") private static RootBeanDefinition createAccessManagerBean(Class... voters) { ManagedList defaultVoters = new ManagedList(voters.length); - for (Class voter : voters) { defaultVoters.add(new RootBeanDefinition(voter)); } - BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); accessMgrBuilder.addConstructorArgValue(defaultVoters); return (RootBeanDefinition) accessMgrBuilder.getBeanDefinition(); diff --git a/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java index 606a5a080d..6b0228de93 100644 --- a/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java @@ -40,6 +40,7 @@ import org.springframework.util.xml.DomUtils; public class MethodSecurityMetadataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser { static final String ATT_METHOD = "method"; + static final String ATT_ACCESS = "access"; @Override @@ -47,17 +48,13 @@ public class MethodSecurityMetadataSourceBeanDefinitionParser extends AbstractBe // Parse the included methods List methods = DomUtils.getChildElementsByTagName(elt, Elements.PROTECT); Map> mappings = new LinkedHashMap<>(); - for (Element protectmethodElt : methods) { String[] tokens = StringUtils.commaDelimitedListToStringArray(protectmethodElt.getAttribute(ATT_ACCESS)); String methodName = protectmethodElt.getAttribute(ATT_METHOD); - mappings.put(methodName, SecurityConfig.createList(tokens)); } - RootBeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); - return metadataSource; } diff --git a/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java b/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java index 8ddecffb07..f35ecc9a88 100644 --- a/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java @@ -82,7 +82,6 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { Assert.notNull(mapBasedMethodSecurityMetadataSource, "MapBasedMethodSecurityMetadataSource to populate is required"); this.mapBasedMethodSecurityMetadataSource = mapBasedMethodSecurityMetadataSource; - // Set up AspectJ pointcut expression parser Set supportedPrimitives = new HashSet<>(3); supportedPrimitives.add(PointcutPrimitive.EXECUTION); @@ -111,22 +110,13 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { // We already have the metadata for this bean return bean; } - synchronized (this.processedBeans) { // check again synchronized this time if (this.processedBeans.contains(beanName)) { return bean; } - // Obtain methods for the present bean - Method[] methods; - try { - methods = bean.getClass().getMethods(); - } - catch (Exception ex) { - throw new IllegalStateException(ex.getMessage()); - } - + Method[] methods = getBeanMethods(bean); // Check to see if any of those methods are compatible with our pointcut // expressions for (Method method : methods) { @@ -139,31 +129,34 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { } } } - this.processedBeans.add(beanName); } - return bean; } + private Method[] getBeanMethods(Object bean) { + try { + return bean.getClass().getMethods(); + } + catch (Exception ex) { + throw new IllegalStateException(ex.getMessage()); + } + } + private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) { // Determine if the presented AspectJ pointcut expression matches this method boolean matches = expression.matchesMethodExecution(method).alwaysMatches(); - // Handle accordingly if (matches) { List attr = this.pointcutMap.get(expression.getPointcutExpression()); - if (logger.isDebugEnabled()) { logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'"); } - this.mapBasedMethodSecurityMetadataSource.addSecureMethod(targetClass, method, attr); } - return matches; } @@ -182,7 +175,6 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { this.pointcutMap.put(pointcutExpression, definition); // Parse the presented AspectJ pointcut expression and add it to the cache this.pointCutExpressions.add(this.parser.parsePointcutExpression(pointcutExpression)); - if (logger.isDebugEnabled()) { logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'"); diff --git a/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java index 8b0a0011f2..78fb3543a7 100644 --- a/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java @@ -87,10 +87,8 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); - Map> providers = getProviders(element); List clientRegistrations = getClientRegistrations(element, parserContext, providers); - BeanDefinition clientRegistrationRepositoryBean = BeanDefinitionBuilder .rootBeanDefinition(InMemoryClientRegistrationRepository.class) .addConstructorArgValue(clientRegistrations).getBeanDefinition(); @@ -98,7 +96,6 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini .generateBeanName(clientRegistrationRepositoryBean); parserContext.registerBeanComponent( new BeanComponentDefinition(clientRegistrationRepositoryBean, clientRegistrationRepositoryId)); - parserContext.popAndRegisterContainingComponent(); return null; } @@ -107,7 +104,6 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini Map> providers) { List clientRegistrationElts = DomUtils.getChildElementsByTagName(element, ELT_CLIENT_REGISTRATION); List clientRegistrations = new ArrayList<>(); - for (Element clientRegistrationElt : clientRegistrationElts) { String registrationId = clientRegistrationElt.getAttribute(ATT_REGISTRATION_ID); String providerId = clientRegistrationElt.getAttribute(ATT_PROVIDER_ID); @@ -134,14 +130,12 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_NAME)).ifPresent(builder::clientName); clientRegistrations.add(builder.build()); } - return clientRegistrations; } private Map> getProviders(Element element) { List providerElts = DomUtils.getChildElementsByTagName(element, ELT_PROVIDER); Map> providers = new HashMap<>(); - for (Element providerElt : providerElts) { Map provider = new HashMap<>(); String providerId = providerElt.getAttribute(ATT_PROVIDER_ID); @@ -162,7 +156,6 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini .ifPresent((value) -> provider.put(ATT_ISSUER_URI, value)); providers.put(providerId, provider); } - return providers; } diff --git a/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java b/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java index ac1ba4b2a8..74cec2b2ca 100644 --- a/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java +++ b/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java @@ -48,6 +48,7 @@ public enum CommonOAuth2Provider { builder.clientName("Google"); return builder; } + }, GITHUB { @@ -64,6 +65,7 @@ public enum CommonOAuth2Provider { builder.clientName("GitHub"); return builder; } + }, FACEBOOK { @@ -80,6 +82,7 @@ public enum CommonOAuth2Provider { builder.clientName("Facebook"); return builder; } + }, OKTA { @@ -93,6 +96,7 @@ public enum CommonOAuth2Provider { builder.clientName("Okta"); return builder; } + }; private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"; diff --git a/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java b/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java index 9e64e4483d..101d5b15c5 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java +++ b/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java @@ -22,43 +22,68 @@ package org.springframework.security.config.web.server; */ public enum SecurityWebFiltersOrder { - FIRST(Integer.MIN_VALUE), HTTP_HEADERS_WRITER, + FIRST(Integer.MIN_VALUE), + + HTTP_HEADERS_WRITER, + /** * {@link org.springframework.security.web.server.transport.HttpsRedirectWebFilter} */ HTTPS_REDIRECT, + /** * {@link org.springframework.web.cors.reactive.CorsWebFilter} */ CORS, + /** * {@link org.springframework.security.web.server.csrf.CsrfWebFilter} */ CSRF, + /** * {@link org.springframework.security.web.server.context.ReactorContextWebFilter} */ REACTOR_CONTEXT, + /** * Instance of AuthenticationWebFilter */ HTTP_BASIC, + /** * Instance of AuthenticationWebFilter */ FORM_LOGIN, AUTHENTICATION, + /** * Instance of AnonymousAuthenticationWebFilter */ - ANONYMOUS_AUTHENTICATION, OAUTH2_AUTHORIZATION_CODE, LOGIN_PAGE_GENERATING, LOGOUT_PAGE_GENERATING, + ANONYMOUS_AUTHENTICATION, + + OAUTH2_AUTHORIZATION_CODE, + + LOGIN_PAGE_GENERATING, + + LOGOUT_PAGE_GENERATING, + /** * {@link org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter} */ SECURITY_CONTEXT_SERVER_WEB_EXCHANGE, + /** * {@link org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter} */ - SERVER_REQUEST_CACHE, LOGOUT, EXCEPTION_TRANSLATION, AUTHORIZATION, LAST(Integer.MAX_VALUE); + SERVER_REQUEST_CACHE, + + LOGOUT, + + EXCEPTION_TRANSLATION, + + AUTHORIZATION, + + LAST(Integer.MAX_VALUE); private static final int INTERVAL = 100; diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index 507be8e960..2cbbaeb231 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -1536,22 +1536,17 @@ public class ServerHttpSecurity { @Override protected Access registerMatcher(ServerWebExchangeMatcher matcher) { - if (this.anyExchangeRegistered) { - throw new IllegalStateException("Cannot register " + matcher - + " which would be unreachable because anyExchange() has already been registered."); - } - if (this.matcher != null) { - throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined"); - } + Assert.state(!this.anyExchangeRegistered, () -> "Cannot register " + matcher + + " which would be unreachable because anyExchange() has already been registered."); + Assert.state(this.matcher == null, + () -> "The matcher " + matcher + " does not have an access rule defined"); this.matcher = matcher; return new Access(); } protected void configure(ServerHttpSecurity http) { - if (this.matcher != null) { - throw new IllegalStateException( - "The matcher " + this.matcher + " does not have an access rule defined"); - } + Assert.state(this.matcher == null, + () -> "The matcher " + this.matcher + " does not have an access rule defined"); AuthorizationWebFilter result = new AuthorizationWebFilter(this.managerBldr.build()); http.addFilterAt(result, SecurityWebFiltersOrder.AUTHORIZATION); } @@ -1722,6 +1717,9 @@ public class ServerHttpSecurity { */ public final class CsrfSpec { + private CsrfSpec() { + } + private CsrfWebFilter filter = new CsrfWebFilter(); private ServerCsrfTokenRepository csrfTokenRepository = new WebSessionServerCsrfTokenRepository(); @@ -1805,9 +1803,6 @@ public class ServerHttpSecurity { http.addFilterAt(this.filter, SecurityWebFiltersOrder.CSRF); } - private CsrfSpec() { - } - } /** @@ -1819,6 +1814,9 @@ public class ServerHttpSecurity { */ public final class ExceptionHandlingSpec { + private ExceptionHandlingSpec() { + } + /** * Configures what to do when the application request authentication * @param authenticationEntryPoint the entry point to use @@ -1850,9 +1848,6 @@ public class ServerHttpSecurity { return ServerHttpSecurity.this; } - private ExceptionHandlingSpec() { - } - } /** @@ -1867,6 +1862,9 @@ public class ServerHttpSecurity { private ServerRequestCache requestCache = new WebSessionServerRequestCache(); + private RequestCacheSpec() { + } + /** * Configures the cache used * @param requestCache the request cache @@ -1901,9 +1899,6 @@ public class ServerHttpSecurity { return and(); } - private RequestCacheSpec() { - } - } /** @@ -1921,6 +1916,9 @@ public class ServerHttpSecurity { private ServerAuthenticationEntryPoint entryPoint = new HttpBasicServerAuthenticationEntryPoint(); + private HttpBasicSpec() { + } + /** * The {@link ReactiveAuthenticationManager} used to authenticate. Defaults to * {@link ServerHttpSecurity#authenticationManager(ReactiveAuthenticationManager)}. @@ -1992,9 +1990,6 @@ public class ServerHttpSecurity { http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC); } - private HttpBasicSpec() { - } - } /** @@ -2025,6 +2020,9 @@ public class ServerHttpSecurity { private ServerAuthenticationSuccessHandler authenticationSuccessHandler = this.defaultSuccessHandler; + private FormLoginSpec() { + } + /** * The {@link ReactiveAuthenticationManager} used to authenticate. Defaults to * {@link ServerHttpSecurity#authenticationManager(ReactiveAuthenticationManager)}. @@ -2177,13 +2175,13 @@ public class ServerHttpSecurity { http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.FORM_LOGIN); } - private FormLoginSpec() { - } - } private final class LoginPageSpec { + private LoginPageSpec() { + } + protected void configure(ServerHttpSecurity http) { if (http.authenticationEntryPoint != null) { return; @@ -2209,9 +2207,6 @@ public class ServerHttpSecurity { } } - private LoginPageSpec() { - } - } /** @@ -2241,6 +2236,11 @@ public class ServerHttpSecurity { private ReferrerPolicyServerHttpHeadersWriter referrerPolicy = new ReferrerPolicyServerHttpHeadersWriter(); + private HeaderSpec() { + this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts, + this.frameOptions, this.xss, this.featurePolicy, this.contentSecurityPolicy, this.referrerPolicy)); + } + /** * Allows method chaining to continue configuring the {@link ServerHttpSecurity} * @return the {@link ServerHttpSecurity} to continue configuring @@ -2437,6 +2437,9 @@ public class ServerHttpSecurity { */ public final class CacheSpec { + private CacheSpec() { + } + /** * Disables cache control response headers * @return the {@link HeaderSpec} to configure @@ -2446,9 +2449,6 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private CacheSpec() { - } - } /** @@ -2458,6 +2458,9 @@ public class ServerHttpSecurity { */ public final class ContentTypeOptionsSpec { + private ContentTypeOptionsSpec() { + } + /** * Disables the content type options response header * @return the {@link HeaderSpec} to configure @@ -2467,9 +2470,6 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private ContentTypeOptionsSpec() { - } - } /** @@ -2479,6 +2479,9 @@ public class ServerHttpSecurity { */ public final class FrameOptionsSpec { + private FrameOptionsSpec() { + } + /** * The mode to configure. Default is * {@link org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode#DENY} @@ -2508,9 +2511,6 @@ public class ServerHttpSecurity { return and(); } - private FrameOptionsSpec() { - } - } /** @@ -2520,6 +2520,9 @@ public class ServerHttpSecurity { */ public final class HstsSpec { + private HstsSpec() { + } + /** * Configures the max age. Default is one year. * @param maxAge the max age @@ -2577,9 +2580,6 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private HstsSpec() { - } - } /** @@ -2613,6 +2613,10 @@ public class ServerHttpSecurity { private static final String DEFAULT_SRC_SELF_POLICY = "default-src 'self'"; + private ContentSecurityPolicySpec() { + HeaderSpec.this.contentSecurityPolicy.setPolicyDirectives(DEFAULT_SRC_SELF_POLICY); + } + /** * Whether to include the {@code Content-Security-Policy-Report-Only} header * in the response. Otherwise, defaults to the {@code Content-Security-Policy} @@ -2648,10 +2652,6 @@ public class ServerHttpSecurity { HeaderSpec.this.contentSecurityPolicy.setPolicyDirectives(policyDirectives); } - private ContentSecurityPolicySpec() { - HeaderSpec.this.contentSecurityPolicy.setPolicyDirectives(DEFAULT_SRC_SELF_POLICY); - } - } /** @@ -2662,6 +2662,10 @@ public class ServerHttpSecurity { */ public final class FeaturePolicySpec { + private FeaturePolicySpec(String policyDirectives) { + HeaderSpec.this.featurePolicy.setPolicyDirectives(policyDirectives); + } + /** * Allows method chaining to continue configuring the * {@link ServerHttpSecurity}. @@ -2671,10 +2675,6 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private FeaturePolicySpec(String policyDirectives) { - HeaderSpec.this.featurePolicy.setPolicyDirectives(policyDirectives); - } - } /** @@ -2686,6 +2686,9 @@ public class ServerHttpSecurity { */ public final class ReferrerPolicySpec { + private ReferrerPolicySpec() { + } + private ReferrerPolicySpec(ReferrerPolicy referrerPolicy) { HeaderSpec.this.referrerPolicy.setPolicy(referrerPolicy); } @@ -2709,14 +2712,6 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private ReferrerPolicySpec() { - } - - } - - private HeaderSpec() { - this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts, - this.frameOptions, this.xss, this.featurePolicy, this.contentSecurityPolicy, this.referrerPolicy)); } } @@ -2736,6 +2731,9 @@ public class ServerHttpSecurity { private List logoutHandlers = new ArrayList<>(Arrays.asList(this.DEFAULT_LOGOUT_HANDLER)); + private LogoutSpec() { + } + /** * Configures the logout handler. Default is * {@code SecurityContextServerLogoutHandler} @@ -2807,12 +2805,10 @@ public class ServerHttpSecurity { if (this.logoutHandlers.isEmpty()) { return null; } - else if (this.logoutHandlers.size() == 1) { + if (this.logoutHandlers.size() == 1) { return this.logoutHandlers.get(0); } - else { - return new DelegatingServerLogoutHandler(this.logoutHandlers); - } + return new DelegatingServerLogoutHandler(this.logoutHandlers); } protected void configure(ServerHttpSecurity http) { @@ -2823,9 +2819,6 @@ public class ServerHttpSecurity { http.addFilterAt(this.logoutWebFilter, SecurityWebFiltersOrder.LOGOUT); } - private LogoutSpec() { - } - } private static class OrderedWebFilter implements WebFilter, Ordered { @@ -2917,7 +2910,6 @@ public class ServerHttpSecurity { if (this.corsFilter != null) { return this.corsFilter; } - CorsConfigurationSource source = getBeanOrNull(CorsConfigurationSource.class); if (source == null) { return null; @@ -2965,7 +2957,6 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); X509PrincipalExtractor principalExtractor = getPrincipalExtractor(); - AuthenticationWebFilter filter = new AuthenticationWebFilter(authenticationManager); filter.setServerAuthenticationConverter(new ServerX509AuthenticationConverter(principalExtractor)); http.addFilterAt(filter, SecurityWebFiltersOrder.AUTHENTICATION); @@ -2975,7 +2966,6 @@ public class ServerHttpSecurity { if (this.principalExtractor != null) { return this.principalExtractor; } - return new SubjectDnX509PrincipalExtractor(); } @@ -2983,12 +2973,8 @@ public class ServerHttpSecurity { if (this.authenticationManager != null) { return this.authenticationManager; } - ReactiveUserDetailsService userDetailsService = getBean(ReactiveUserDetailsService.class); - ReactivePreAuthenticatedAuthenticationManager authenticationManager = new ReactivePreAuthenticatedAuthenticationManager( - userDetailsService); - - return authenticationManager; + return new ReactivePreAuthenticatedAuthenticationManager(userDetailsService); } } @@ -3095,21 +3081,21 @@ public class ServerHttpSecurity { } boolean oidcAuthenticationProviderEnabled = ClassUtils .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); - if (oidcAuthenticationProviderEnabled) { - OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( - client, getOidcUserService()); - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, - ClientRegistration.class); - ReactiveJwtDecoderFactory jwtDecoderFactory = getBeanOrNull(type); - if (jwtDecoderFactory != null) { - oidc.setJwtDecoderFactory(jwtDecoderFactory); - } - if (authoritiesMapper != null) { - oidc.setAuthoritiesMapper(authoritiesMapper); - } - return new DelegatingReactiveAuthenticationManager(oidc, oauth2Manager); + if (!oidcAuthenticationProviderEnabled) { + return oauth2Manager; } - return oauth2Manager; + OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( + client, getOidcUserService()); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, + ClientRegistration.class); + ReactiveJwtDecoderFactory jwtDecoderFactory = getBeanOrNull(type); + if (jwtDecoderFactory != null) { + oidc.setJwtDecoderFactory(jwtDecoderFactory); + } + if (authoritiesMapper != null) { + oidc.setAuthoritiesMapper(authoritiesMapper); + } + return new DelegatingReactiveAuthenticationManager(oidc, oauth2Manager); } /** @@ -3124,17 +3110,17 @@ public class ServerHttpSecurity { private ServerAuthenticationConverter getAuthenticationConverter( ReactiveClientRegistrationRepository clientRegistrationRepository) { - if (this.authenticationConverter == null) { - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( - clientRegistrationRepository); - delegate.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - ServerAuthenticationConverter authenticationConverter = (exchange) -> delegate.convert(exchange) - .onErrorMap(OAuth2AuthorizationException.class, - (e) -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())); - this.authenticationConverter = authenticationConverter; - return authenticationConverter; + if (this.authenticationConverter != null) { + return this.authenticationConverter; } - return this.authenticationConverter; + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + clientRegistrationRepository); + delegate.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); + ServerAuthenticationConverter authenticationConverter = (exchange) -> delegate.convert(exchange).onErrorMap( + OAuth2AuthorizationException.class, + (e) -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())); + this.authenticationConverter = authenticationConverter; + return authenticationConverter; } public OAuth2LoginSpec clientRegistrationRepository( @@ -3216,21 +3202,16 @@ public class ServerHttpSecurity { ServerAuthorizationRequestRepository authorizationRequestRepository = getAuthorizationRequestRepository(); oauthRedirectFilter.setAuthorizationRequestRepository(authorizationRequestRepository); oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); - ReactiveAuthenticationManager manager = getAuthenticationManager(); - AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, authorizedClientRepository); authenticationFilter.setRequiresAuthenticationMatcher(getAuthenticationMatcher()); authenticationFilter .setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository)); - authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http)); authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler()); authenticationFilter.setSecurityContextRepository(this.securityContextRepository); - setDefaultEntryPoints(http); - http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION); } @@ -3242,12 +3223,10 @@ public class ServerHttpSecurity { if (urlToText.size() == 1) { providerLoginPage = urlToText.keySet().iterator().next(); } - MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher( MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN); htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - ServerWebExchangeMatcher xhrMatcher = (exchange) -> { if (exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest")) { return ServerWebExchangeMatcher.MatchResult.match(); @@ -3255,10 +3234,8 @@ public class ServerHttpSecurity { return ServerWebExchangeMatcher.MatchResult.notMatch(); }; ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher); - ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(notXhrMatcher, htmlMatcher); - if (providerLoginPage != null) { ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher( defaultLoginPage); @@ -3273,7 +3250,6 @@ public class ServerHttpSecurity { entryPoint.setRequestCache(http.requestCache.requestCache); http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint)); } - RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint( defaultLoginPage); defaultEntryPoint.setRequestCache(http.requestCache.requestCache); @@ -3304,22 +3280,20 @@ public class ServerHttpSecurity { ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, OidcUserRequest.class, OidcUser.class); ReactiveOAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - return new OidcReactiveOAuth2UserService(); + if (bean != null) { + return bean; } - - return bean; + return new OidcReactiveOAuth2UserService(); } private ReactiveOAuth2UserService getOauth2UserService() { ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, OAuth2UserRequest.class, OAuth2User.class); ReactiveOAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - return new DefaultReactiveOAuth2UserService(); + if (bean != null) { + return bean; } - - return bean; + return new DefaultReactiveOAuth2UserService(); } private Map getLinks() { @@ -3338,10 +3312,10 @@ public class ServerHttpSecurity { ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, OAuth2AuthorizationCodeGrantRequest.class); ReactiveOAuth2AccessTokenResponseClient bean = getBeanOrNull(type); - if (bean == null) { - return new WebClientReactiveAuthorizationCodeTokenResponseClient(); + if (bean != null) { + return bean; } - return bean; + return new WebClientReactiveAuthorizationCodeTokenResponseClient(); } private ReactiveClientRegistrationRepository getClientRegistrationRepository() { @@ -3353,15 +3327,10 @@ public class ServerHttpSecurity { private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() { OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter; - if (this.authorizationRequestResolver == null) { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( - getClientRegistrationRepository()); + if (this.authorizationRequestResolver != null) { + return new OAuth2AuthorizationRequestRedirectWebFilter(this.authorizationRequestResolver); } - else { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( - this.authorizationRequestResolver); - } - return oauthRedirectFilter; + return new OAuth2AuthorizationRequestRedirectWebFilter(getClientRegistrationRepository()); } private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() { @@ -3386,11 +3355,11 @@ public class ServerHttpSecurity { } private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { - ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); - if (service == null) { - service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); + ReactiveOAuth2AuthorizedClientService bean = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); + if (bean != null) { + return bean; } - return service; + return new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); } } @@ -3518,14 +3487,12 @@ public class ServerHttpSecurity { if (http.requestCache != null) { codeGrantWebFilter.setRequestCache(http.requestCache.requestCache); } - OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( clientRegistrationRepository); oauthRedirectFilter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); if (http.requestCache != null) { oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); } - http.addFilterAt(codeGrantWebFilter, SecurityWebFiltersOrder.OAUTH2_AUTHORIZATION_CODE); http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); } @@ -3542,21 +3509,22 @@ public class ServerHttpSecurity { return this.authorizedClientRepository; } ServerOAuth2AuthorizedClientRepository result = getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class); - if (result == null) { - ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); - if (authorizedClientService != null) { - result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); - } + if (result != null) { + return result; } - return result; + ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); + if (authorizedClientService != null) { + return new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); + } + return null; } private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { - ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); - if (service == null) { - service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); + ReactiveOAuth2AuthorizedClientService bean = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); + if (bean != null) { + return bean; } - return service; + return new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); } } @@ -3692,13 +3660,10 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { this.authenticationConverterServerWebExchangeMatcher = new AuthenticationConverterServerWebExchangeMatcher( this.bearerTokenConverter); - registerDefaultAccessDeniedHandler(http); registerDefaultAuthenticationEntryPoint(http); registerDefaultCsrfOverride(http); - validateConfiguration(); - if (this.authenticationManagerResolver != null) { AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.authenticationManagerResolver); oauth2.setServerAuthenticationConverter(this.bearerTokenConverter); @@ -3716,25 +3681,18 @@ public class ServerHttpSecurity { private void validateConfiguration() { if (this.authenticationManagerResolver == null) { - if (this.jwt == null && this.opaqueToken == null) { - throw new IllegalStateException( - "Jwt and Opaque Token are the only supported formats for bearer tokens " - + "in Spring Security and neither was found. Make sure to configure JWT " - + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " - + "http.oauth2ResourceServer().opaqueToken()."); - } - - if (this.jwt != null && this.opaqueToken != null) { - throw new IllegalStateException( - "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); - } + Assert.state(this.jwt != null || this.opaqueToken != null, + "Jwt and Opaque Token are the only supported formats for bearer tokens " + + "in Spring Security and neither was found. Make sure to configure JWT " + + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " + + "http.oauth2ResourceServer().opaqueToken()."); + Assert.state(this.jwt == null || this.opaqueToken == null, + "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); } else { - if (this.jwt != null || this.opaqueToken != null) { - throw new IllegalStateException( - "If an authenticationManagerResolver() is configured, then it takes " - + "precedence over any jwt() or opaqueToken() configuration."); - } + Assert.state(this.jwt == null && this.opaqueToken == null, + "If an authenticationManagerResolver() is configured, then it takes " + + "precedence over any jwt() or opaqueToken() configuration."); } } @@ -3756,15 +3714,10 @@ public class ServerHttpSecurity { private void registerDefaultCsrfOverride(ServerHttpSecurity http) { if (http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher) { - // @formatter:off - http - .csrf() - .requireCsrfProtectionMatcher( - new AndServerWebExchangeMatcher( - CsrfWebFilter.DEFAULT_CSRF_MATCHER, - new NegatedServerWebExchangeMatcher( - this.authenticationConverterServerWebExchangeMatcher))); - // @formatter:on + AndServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher( + CsrfWebFilter.DEFAULT_CSRF_MATCHER, + new NegatedServerWebExchangeMatcher(this.authenticationConverterServerWebExchangeMatcher)); + http.csrf().requireCsrfProtectionMatcher(matcher); } } @@ -3876,21 +3829,14 @@ public class ServerHttpSecurity { oauth2.setServerAuthenticationConverter(OAuth2ResourceServerSpec.this.bearerTokenConverter); oauth2.setAuthenticationFailureHandler( new ServerAuthenticationEntryPointFailureHandler(OAuth2ResourceServerSpec.this.entryPoint)); - // @formatter:off - http - .addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); - // @formatter:on + http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); } protected ReactiveJwtDecoder getJwtDecoder() { - if (this.jwtDecoder == null) { - return getBean(ReactiveJwtDecoder.class); - } - return this.jwtDecoder; + return (this.jwtDecoder != null) ? this.jwtDecoder : getBean(ReactiveJwtDecoder.class); } protected Converter> getJwtAuthenticationConverter() { - return this.jwtAuthenticationConverter; } @@ -3898,13 +3844,11 @@ public class ServerHttpSecurity { if (this.authenticationManager != null) { return this.authenticationManager; } - ReactiveJwtDecoder jwtDecoder = getJwtDecoder(); Converter> jwtAuthenticationConverter = getJwtAuthenticationConverter(); JwtReactiveAuthenticationManager authenticationManager = new JwtReactiveAuthenticationManager( jwtDecoder); authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverter); - return authenticationManager; } diff --git a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java index a5316adec5..ba8d3ac4e0 100644 --- a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java @@ -116,26 +116,20 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); XmlReaderContext context = parserContext.getReaderContext(); - ManagedMap matcherToExpression = new ManagedMap<>(); - String id = element.getAttribute(ID_ATTR); Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER); String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref") : null; boolean expressionHandlerDefined = StringUtils.hasText(expressionHandlerRef); - boolean sameOriginDisabled = Boolean.parseBoolean(element.getAttribute(DISABLED_ATTR)); - List interceptMessages = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_MESSAGE); for (Element interceptMessage : interceptMessages) { String matcherPattern = interceptMessage.getAttribute(PATTERN_ATTR); String accessExpression = interceptMessage.getAttribute(ACCESS_ATTR); String messageType = interceptMessage.getAttribute(TYPE_ATTR); - BeanDefinition matcher = createMatcher(matcherPattern, messageType, parserContext, interceptMessage); matcherToExpression.put(matcher, accessExpression); } - BeanDefinitionBuilder mds = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedMessageSecurityMetadataSourceFactory.class); mds.setFactoryMethod("createExpressionMessageMetadataSource"); @@ -143,9 +137,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements if (expressionHandlerDefined) { mds.addConstructorArgReference(expressionHandlerRef); } - String mdsId = context.registerWithGeneratedName(mds.getBeanDefinition()); - ManagedList voters = new ManagedList<>(); BeanDefinitionBuilder messageExpressionVoterBldr = BeanDefinitionBuilder .rootBeanDefinition(MessageExpressionVoter.class); @@ -155,17 +147,14 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements voters.add(messageExpressionVoterBldr.getBeanDefinition()); BeanDefinitionBuilder adm = BeanDefinitionBuilder.rootBeanDefinition(ConsensusBased.class); adm.addConstructorArgValue(voters); - BeanDefinitionBuilder inboundChannelSecurityInterceptor = BeanDefinitionBuilder .rootBeanDefinition(ChannelSecurityInterceptor.class); inboundChannelSecurityInterceptor.addConstructorArgValue(registry.getBeanDefinition(mdsId)); inboundChannelSecurityInterceptor.addPropertyValue("accessDecisionManager", adm.getBeanDefinition()); String inSecurityInterceptorName = context .registerWithGeneratedName(inboundChannelSecurityInterceptor.getBeanDefinition()); - if (StringUtils.hasText(id)) { registry.registerAlias(inSecurityInterceptorName, id); - if (!registry.containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) { registry.registerBeanDefinition(PATH_MATCHER_BEAN_NAME, new RootBeanDefinition(AntPathMatcher.class)); } @@ -176,7 +165,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements mspp.addConstructorArgValue(sameOriginDisabled); context.registerWithGeneratedName(mspp.getBeanDefinition()); } - return null; } @@ -189,7 +177,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements matcher.addConstructorArgValue(messageType); return matcher.getBeanDefinition(); } - String factoryName = null; if (hasPattern && hasMessageType) { SimpMessageType type = SimpMessageType.valueOf(messageType); @@ -204,7 +191,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements + " with a pattern because the type does not have a destination.", interceptMessage); } } - BeanDefinitionBuilder matcher = BeanDefinitionBuilder.rootBeanDefinition(SimpDestinationMessageMatcher.class); matcher.setFactoryMethod(factoryName); matcher.addConstructorArgValue(matcherPattern); @@ -249,7 +235,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements } argResolvers.add(new RootBeanDefinition(AuthenticationPrincipalArgumentResolver.class)); bd.getPropertyValues().add(CUSTOM_ARG_RESOLVERS_PROP, argResolvers); - if (!registry.containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) { PropertyValue pathMatcherProp = bd.getPropertyValues().getPropertyValue("pathMatcher"); Object pathMatcher = (pathMatcherProp != null) ? pathMatcherProp.getValue() : null; @@ -271,7 +256,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements addCsrfTokenHandshakeInterceptor(bd); } } - if (!registry.containsBeanDefinition(CLIENT_INBOUND_CHANNEL_BEAN_ID)) { return; } @@ -281,7 +265,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements interceptors.add(new RootBeanDefinition(CsrfChannelInterceptor.class)); } interceptors.add(registry.getBeanDefinition(this.inboundSecurityInterceptorId)); - BeanDefinition inboundChannel = registry.getBeanDefinition(CLIENT_INBOUND_CHANNEL_BEAN_ID); PropertyValue currentInterceptorsPv = inboundChannel.getPropertyValues() .getPropertyValue(INTERCEPTORS_PROP); @@ -289,9 +272,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements ManagedList currentInterceptors = (ManagedList) currentInterceptorsPv.getValue(); interceptors.addAll(currentInterceptors); } - inboundChannel.getPropertyValues().add(INTERCEPTORS_PROP, interceptors); - if (!registry.containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) { registry.registerBeanDefinition(PATH_MATCHER_BEAN_NAME, new RootBeanDefinition(AntPathMatcher.class)); }