Move "realm" attribute to be on <http> element rather than <http-basic>.
This faciltiates reuse with other mechanisms (like Digest) whilst also moving towards the <http-auto-configure> element (which benefits from having shared configuration in <http> as opposed to mechanism-specific elements).
This commit is contained in:
parent
d9ec944579
commit
2441ab6d9a
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* <ol>
|
||||
* <li>If only one use that.</li>
|
||||
* <li>If more than one, check the default interactive login Ids in order of preference</li>
|
||||
* <li>throw an exception (for now). TODO: Examine additional beans and types and make decision</li>
|
||||
* <li>If only one, use that one.</li>
|
||||
* <li>If more than one, use the form login entry point (if form login is being used)</li>
|
||||
* <li>If still ambiguous, throw an exception (for now). TODO: Examine additional beans and types and make decision</li>
|
||||
* </ol>
|
||||
*
|
||||
*/
|
||||
private void configureAuthenticationEntryPoint(ConfigurableListableBeanFactory beanFactory) {
|
||||
private void injectAuthenticationEntryPointIntoExceptionTranslationFilter(ConfigurableListableBeanFactory beanFactory) {
|
||||
logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter");
|
||||
|
||||
BeanDefinition etf =
|
||||
|
|
|
@ -71,6 +71,9 @@ http.attlist &=
|
|||
http.attlist &=
|
||||
## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.
|
||||
attribute accessDecisionManager {xsd:string}?
|
||||
http.attlist &=
|
||||
## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
|
||||
attribute realm {xsd:string}?
|
||||
|
||||
|
||||
intercept-url =
|
||||
|
@ -129,10 +132,9 @@ filter-chain.attlist &=
|
|||
attribute filters {xsd:string}
|
||||
|
||||
http-basic =
|
||||
## Adds support for basic authentication
|
||||
element http-basic {http-basic.attlist, empty}
|
||||
http-basic.attlist &=
|
||||
attribute realm {xsd:string}
|
||||
## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
|
||||
element http-basic {empty}
|
||||
|
||||
|
||||
concurrent-session-control =
|
||||
## Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have.
|
||||
|
|
|
@ -146,6 +146,11 @@
|
|||
<xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="realm" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="intercept-url">
|
||||
<xs:annotation>
|
||||
|
@ -263,15 +268,10 @@
|
|||
</xs:attributeGroup>
|
||||
<xs:element name="http-basic">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds support for basic authentication</xs:documentation>
|
||||
<xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:attributeGroup ref="security:http-basic.attlist"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType/>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="http-basic.attlist">
|
||||
<xs:attribute name="realm" use="required" type="xs:string"/>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="concurrent-session-control">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have.</xs:documentation>
|
||||
|
|
|
@ -15,7 +15,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||
<form-login loginUrl="/j_spring_security_check" />
|
||||
|
||||
<!-- Default basic auth configuration. Will create filter and entry point -->
|
||||
<http-basic realm="NamespaceTestRealm" />
|
||||
<http-basic/>
|
||||
|
||||
<!-- Default logout configuration -->
|
||||
<logout logoutUrl="/j_spring_security_logout" logoutSuccessUrl="/" invalidateSession="true" />
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<form-login />
|
||||
<anonymous />
|
||||
<http-basic realm="SpringSecurityTutorialApp" />
|
||||
<http-basic />
|
||||
<logout />
|
||||
<concurrent-session-control maxSessions="1" exceptionIfMaximumExceeded="true"/>
|
||||
|
||||
|
|
Loading…
Reference in New Issue