diff --git a/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java index a2ddc3dafb..e7f7b4d988 100644 --- a/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java @@ -1,6 +1,7 @@ package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; @@ -18,26 +19,27 @@ import org.w3c.dom.Element; * @version $Id$ */ public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionParser { - static final String ATT_REALM = "realm"; + private String realmName; + + public BasicAuthenticationBeanDefinitionParser(String realmName) { + this.realmName = realmName; + } public BeanDefinition parse(Element elt, ParserContext parserContext) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicProcessingFilter.class); RootBeanDefinition entryPoint = new RootBeanDefinition(BasicProcessingFilterEntryPoint.class); - String realm = elt.getAttribute(ATT_REALM); - - entryPoint.getPropertyValues().addPropertyValue("realmName", realm); + entryPoint.getPropertyValues().addPropertyValue("realmName", realmName); filterBuilder.addPropertyValue("authenticationEntryPoint", entryPoint); + parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, entryPoint); + + filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); + filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT)); - // TODO: Remove autowiring approach from here. - // Detect auth manager - filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); - parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_FILTER, filterBuilder.getBeanDefinition()); - parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, entryPoint); return null; } diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java index b55ef50f07..c4ed8cd450 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -44,6 +44,9 @@ import java.util.Map; */ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { + static final String ATT_REALM = "realm"; + static final String DEF_REALM = "Spring Security Application"; + static final String ATT_PATH_PATTERN = "pattern"; static final String ATT_PATTERN_TYPE = "pathType"; static final String ATT_PATTERN_TYPE_REGEX = "regex"; @@ -149,11 +152,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { if (formLoginElt != null) { new FormLoginBeanDefinitionParser().parse(formLoginElt, parserContext); } + + String realm = element.getAttribute(ATT_REALM); + if (!StringUtils.hasText(realm)) { + realm = DEF_REALM; + } Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH); if (basicAuthElt != null) { - new BasicAuthenticationBeanDefinitionParser().parse(basicAuthElt, parserContext); + new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext); } registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy); diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java b/core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java index dd8e8e280a..8a4a13d090 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java @@ -1,11 +1,15 @@ package org.springframework.security.config; -import org.springframework.security.concurrent.ConcurrentSessionFilter; -import org.springframework.security.context.HttpSessionContextIntegrationFilter; -import org.springframework.security.ui.AbstractProcessingFilter; -import org.springframework.security.ui.AuthenticationEntryPoint; -import org.springframework.security.ui.rememberme.RememberMeServices; -import org.springframework.security.util.FilterChainProxy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.Filter; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; @@ -13,23 +17,21 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; +import org.springframework.security.concurrent.ConcurrentSessionFilter; +import org.springframework.security.context.HttpSessionContextIntegrationFilter; +import org.springframework.security.ui.AbstractProcessingFilter; +import org.springframework.security.ui.AuthenticationEntryPoint; +import org.springframework.security.ui.basicauth.BasicProcessingFilter; +import org.springframework.security.ui.rememberme.RememberMeServices; +import org.springframework.security.util.FilterChainProxy; import org.springframework.util.Assert; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.servlet.Filter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - /** * Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up * with other beans. * * @author Luke Taylor + * @author Ben Alex * @version $Id$ */ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered { @@ -42,16 +44,16 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor ConfigUtils.configureSecurityInterceptor(beanFactory, securityInterceptor); - configureRememberMeSerices(beanFactory); + injectUserDetailsServiceIntoRememberMeServices(beanFactory); - configureAuthenticationEntryPoint(beanFactory); + injectAuthenticationEntryPointIntoExceptionTranslationFilter(beanFactory); - configureAuthenticationFilter(beanFactory); + injectRememberMeServicesIntoFiltersRequiringIt(beanFactory); configureFilterChain(beanFactory); } - private void configureRememberMeSerices(ConfigurableListableBeanFactory beanFactory) { + private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory beanFactory) { try { BeanDefinition rememberMeServices = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES); @@ -66,7 +68,7 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor * Sets the authentication manager, (and remember-me services, if required) on any instances of * AbstractProcessingFilter */ - private void configureAuthenticationFilter(ConfigurableListableBeanFactory beanFactory) { + private void injectRememberMeServicesIntoFiltersRequiringIt(ConfigurableListableBeanFactory beanFactory) { Map beans = beanFactory.getBeansOfType(RememberMeServices.class); RememberMeServices rememberMeServices = null; @@ -75,29 +77,43 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor rememberMeServices = (RememberMeServices) beans.values().toArray()[0]; } - Iterator authFilters = beanFactory.getBeansOfType(AbstractProcessingFilter.class).values().iterator(); + // Address AbstractProcessingFilter instances + Iterator filters = beanFactory.getBeansOfType(AbstractProcessingFilter.class).values().iterator(); - while (authFilters.hasNext()) { - AbstractProcessingFilter filter = (AbstractProcessingFilter) authFilters.next(); + while (filters.hasNext()) { + AbstractProcessingFilter filter = (AbstractProcessingFilter) filters.next(); if (rememberMeServices != null) { logger.info("Using RememberMeServices " + rememberMeServices + " with filter " + filter); filter.setRememberMeServices(rememberMeServices); } } + + // Address BasicProcessingFilter instance, if it exists + // NB: For remember-me to be sent back, a user must submit a "_spring_security_remember_me" with their login request. + // Most of the time a user won't present such a parameter with their BASIC authentication request. + // In the future we might support setting the AbstractRememberMeServices.alwaysRemember = true, but I am reluctant to + // do so because it seems likely to lead to lower security for 99.99% of users if they set the property to true. + BasicProcessingFilter filter = (BasicProcessingFilter) getBeanOfType(BasicProcessingFilter.class, beanFactory); + + if (filter != null && rememberMeServices != null) { + logger.info("Using RememberMeServices " + rememberMeServices + " with filter " + filter); + filter.setRememberMeServices(rememberMeServices); + } + } /** * Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is * *