SEC-645: Reimplementation of X509 provider and namespace implementation.

This commit is contained in:
Luke Taylor 2008-01-27 22:45:44 +00:00
parent 9af7ab68bf
commit acf5601714
12 changed files with 237 additions and 73 deletions

View File

@ -2,6 +2,8 @@ package org.springframework.security.config;
/** /**
* Contains all the default Bean IDs created by the namespace support in Spring Security 2. * Contains all the default Bean IDs created by the namespace support in Spring Security 2.
* <p>
* These are mainly intended for internal use.
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$
@ -44,4 +46,7 @@ public abstract class BeanIds {
public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer"; public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer";
public static final String CONTEXT_SOURCE = "_securityContextSource"; public static final String CONTEXT_SOURCE = "_securityContextSource";
public static final String PORT_MAPPER = "_portMapper"; public static final String PORT_MAPPER = "_portMapper";
public static final String X509_FILTER = "_x509ProcessingFilter";
public static final String X509_AUTH_PROVIDER = "_x509AuthenitcationProvider";
public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
} }

View File

@ -31,4 +31,5 @@ abstract class Elements {
public static final String PORT_MAPPING = "port-mapping"; public static final String PORT_MAPPING = "port-mapping";
public static final String CUSTOM_FILTER = "custom-filter"; public static final String CUSTOM_FILTER = "custom-filter";
public static final String CUSTOM_AUTH_RPOVIDER = "custom-authentication-provider"; public static final String CUSTOM_AUTH_RPOVIDER = "custom-authentication-provider";
public static final String X509 = "x509";
} }

View File

@ -256,6 +256,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext); new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext);
} }
Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
if (x509Elt != null) {
new X509BeanDefinitionParser().parse(x509Elt, parserContext);
}
registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy); registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
registry.registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif); registry.registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
registry.registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition()); registry.registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());

View File

@ -11,6 +11,7 @@ import javax.servlet.Filter;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@ -24,6 +25,7 @@ import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilter;
import org.springframework.security.ui.rememberme.RememberMeServices; import org.springframework.security.ui.rememberme.RememberMeServices;
import org.springframework.security.util.FilterChainProxy; import org.springframework.security.util.FilterChainProxy;
import org.springframework.security.providers.preauth.UserDetailsByNameServiceWrapper;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -33,12 +35,14 @@ import org.springframework.util.Assert;
* @author Luke Taylor * @author Luke Taylor
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$
* @since 2.0
*/ */
public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered { public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
private Log logger = LogFactory.getLog(getClass()); private Log logger = LogFactory.getLog(getClass());
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
injectUserDetailsServiceIntoRememberMeServices(beanFactory); injectUserDetailsServiceIntoRememberMeServices(beanFactory);
injectUserDetailsServiceIntoX509Provider(beanFactory);
injectAuthenticationEntryPointIntoExceptionTranslationFilter(beanFactory); injectAuthenticationEntryPointIntoExceptionTranslationFilter(beanFactory);
@ -50,8 +54,28 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory beanFactory) { private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory beanFactory) {
try { try {
BeanDefinition rememberMeServices = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES); BeanDefinition rememberMeServices = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService", PropertyValue pv = rememberMeServices.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService",
ConfigUtils.getUserDetailsService(beanFactory)); ConfigUtils.getUserDetailsService(beanFactory));
}
} catch (NoSuchBeanDefinitionException e) {
// ignore
}
}
private void injectUserDetailsServiceIntoX509Provider(ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition x509AuthProvider = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
PropertyValue pv = x509AuthProvider.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
if (pv == null) {
UserDetailsByNameServiceWrapper preAuthUserService = new UserDetailsByNameServiceWrapper();
preAuthUserService.setUserDetailsService(ConfigUtils.getUserDetailsService(beanFactory));
x509AuthProvider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService",
preAuthUserService);
}
} catch (NoSuchBeanDefinitionException e) { } catch (NoSuchBeanDefinitionException e) {
// ignore // ignore
} }

View File

@ -0,0 +1,64 @@
package org.springframework.security.config;
import org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint;
import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter;
import org.springframework.security.ui.preauth.x509.SubjectDnX509PrincipalExtractor;
import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider;
import org.springframework.security.providers.preauth.UserDetailsByNameServiceWrapper;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
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.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parses x509 element in namespace, registering an {@link X509PreAuthenticatedProcessingFilter} instance and a
* {@link PreAuthenticatedProcessingFilterEntryPoint}.
*
* @author Luke Taylor
* @version $Id$
* @since 2.0
*/
public class X509BeanDefinitionParser implements BeanDefinitionParser {
public static final String ATT_REGEX = "subject-principal-regex";
public static final String ATT_USER_SERVICE_REF = "user-service-ref";
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509PreAuthenticatedProcessingFilter.class);
RootBeanDefinition entryPoint = new RootBeanDefinition(PreAuthenticatedProcessingFilterEntryPoint.class);
String regex = element.getAttribute(ATT_REGEX);
if (StringUtils.hasText(regex)) {
SubjectDnX509PrincipalExtractor extractor = new SubjectDnX509PrincipalExtractor();
extractor.setSubjectDnRegex(regex);
filterBuilder.addPropertyValue("principalExtractor", extractor);
}
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
ConfigUtils.getRegisteredProviders(parserContext).add(provider);
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider);
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
if (StringUtils.hasText(userServiceRef)) {
RuntimeBeanReference userService = new RuntimeBeanReference(userServiceRef);
BeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", userService);
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
}
parserContext.getRegistry().registerBeanDefinition(BeanIds.PRE_AUTH_ENTRY_POINT, entryPoint);
filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_FILTER, filterBuilder.getBeanDefinition());
return null;
}
}

View File

@ -24,6 +24,7 @@ import org.springframework.util.Assert;
* a UsernameNotFoundException. * a UsernameNotFoundException.
* *
* @author Ruud Senden * @author Ruud Senden
* @version $Id$
* @since 2.0 * @since 2.0
*/ */
public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered { public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered {

View File

@ -62,11 +62,11 @@ public abstract class FilterChainOrder {
} }
/** Allows filters to be used by name in the XSD file without explicit reference to Java constants */ /** Allows filters to be used by name in the XSD file without explicit reference to Java constants */
public static Integer getOrder(String filterName) { public static int getOrder(String filterName) {
Integer order = (Integer) filterNameToOrder.get(filterName); Integer order = (Integer) filterNameToOrder.get(filterName);
Assert.notNull(order, "Unable to match filter name " + filterName); Assert.notNull(order, "Unable to match filter name " + filterName);
return order; return order.intValue();
} }
} }

View File

@ -31,6 +31,10 @@ public class X509PreAuthenticatedProcessingFilter extends AbstractPreAuthenticat
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
if (certs != null && certs.length > 0) { if (certs != null && certs.length > 0) {
if (logger.isDebugEnabled()) {
logger.debug("X.509 client authentication certificate:" + certs[0]);
}
return certs[0]; return certs[0];
} }

View File

@ -27,9 +27,13 @@ id =
## A bean identifier, used for referring to the bean elsewhere in the context. ## A bean identifier, used for referring to the bean elsewhere in the context.
attribute id {xsd:ID} attribute id {xsd:ID}
ref = ref =
## Defines a reference to a Spring bean id. ## Defines a reference to a Spring bean Id.
attribute ref {xsd:string} attribute ref {xsd:string}
user-service-ref =
## A reference to a user-service (or UserDetailsService bean) Id
attribute user-service-ref {xsd:string}
password-encoder = password-encoder =
## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. ## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
element password-encoder {ref | (hash? & base64? & salt-source*)} element password-encoder {ref | (hash? & base64? & salt-source*)}
@ -88,7 +92,7 @@ protect.attlist &=
annotation-driven = annotation-driven =
## Activates security annotation scanning. All beans registered in the Spring application context will be scanned for Spring Security annotations. Where found, the beans will automatically be proxied and security authorization applied to the methods accordingly. Please ensure you have the spring-security-tiger-XXX.jar on your classpath. ## Activates security annotation scanning. All beans registered in the Spring application context will be scanned for Spring Security annotations. Where found, the beans will automatically be proxied and security authorization applied to the methods accordingly. Please ensure you have the spring-security-tiger-XXX.jar on your classpath.
element annotation-driven {annotation-driven.attlist} element annotation-driven {annotation-driven.attlist}
annotation-driven.attlist &= annotation-driven.attlist &=
## Specifies that JSR-250 style attributes are to be used (for example "RolesAllowed" instead of "Secured"). This will require the javax.annotation.security classes on the classpath. Defaults to false. ## Specifies that JSR-250 style attributes are to be used (for example "RolesAllowed" instead of "Secured"). This will require the javax.annotation.security classes on the classpath. Defaults to false.
@ -99,7 +103,7 @@ annotation-driven.attlist &=
http = http =
## Container element for HTTP security configuration ## Container element for HTTP security configuration
element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & port-mappings) } element http {http.attlist, (intercept-url+ & form-login? & x509? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & port-mappings) }
http.attlist &= http.attlist &=
## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". ## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".
attribute auto-config {"true" | "false" }? attribute auto-config {"true" | "false" }?
@ -207,48 +211,18 @@ remember-me.attlist &=
(attribute key {xsd:string} | (attribute token-repository-ref {xsd:string} | attribute data-source-ref {xsd:string})) (attribute key {xsd:string} | (attribute token-repository-ref {xsd:string} | attribute data-source-ref {xsd:string}))
anonymous = anonymous =
## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. ## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
element anonymous {anonymous.attlist} element anonymous {anonymous.attlist}
anonymous.attlist &= anonymous.attlist &=
## The key used between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". ## The key used between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
attribute key {xsd:string}? attribute key {xsd:string}?
anonymous.attlist &= anonymous.attlist &=
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". ## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
attribute username {xsd:string}? attribute username {xsd:string}?
anonymous.attlist &= anonymous.attlist &=
## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". ## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
attribute granted-authority {xsd:string}? attribute granted-authority {xsd:string}?
authentication-provider =
## Indicates that the contained user-service should be used as an authentication source.
element authentication-provider {ap.attlist & (user-service | jdbc-user-service) & password-encoder}
ap.attlist &=
## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
attribute user-service-ref {xsd:string}?
custom-authentication-provider =
element custom-authentication-provider {cap.attlist}
cap.attlist &= empty
user-service =
## Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.
element user-service {id? & (properties-file | (user*))}
properties-file =
attribute properties {xsd:string}?
user =
## Represents a user in the application.
element user {user.attlist, empty}
user.attlist &=
## The username assigned to the user.
attribute name {xsd:string}
user.attlist &=
## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element).
attribute password {xsd:string}
user.attlist &=
## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
attribute authorities {xsd:string}
port-mappings = port-mappings =
## Defines the list of mappings between http and https ports for use in redirects ## Defines the list of mappings between http and https ports for use in redirects
element port-mappings {port-mappings.attlist, port-mapping+} element port-mappings {port-mappings.attlist, port-mapping+}
@ -262,11 +236,52 @@ http-port = attribute http {xsd:integer}
https-port = attribute https {xsd:integer} https-port = attribute https {xsd:integer}
x509 =
## Adds support for X.509 client authentication.
element x509 {x509.attlist}
x509.attlist &=
## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".
attribute subject-principal-regex {xsd:string}?
x509.attlist &=
## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
user-service-ref?
authentication-provider =
## Indicates that the contained user-service should be used as an authentication source.
element authentication-provider {ap.attlist & (user-service | jdbc-user-service) & password-encoder}
ap.attlist &=
## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
user-service-ref?
custom-authentication-provider =
element custom-authentication-provider {cap.attlist}
cap.attlist &= empty
user-service =
## Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.
element user-service {id? & (properties-file | (user*))}
properties-file =
attribute properties {xsd:string}?
user =
## Represents a user in the application.
element user {user.attlist, empty}
user.attlist &=
## The username assigned to the user.
attribute name {xsd:string}
user.attlist &=
## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element).
attribute password {xsd:string}
user.attlist &=
## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
attribute authorities {xsd:string}
jdbc-user-service = jdbc-user-service =
## Causes creation of a JDBC-based UserDetailsService. ## Causes creation of a JDBC-based UserDetailsService.
element jdbc-user-service {id? & jdbc-user-service.attlist} element jdbc-user-service {id? & jdbc-user-service.attlist}
jdbc-user-service.attlist &= jdbc-user-service.attlist &=
## The bean ID of the DataSource which provides the required tables. ## The bean ID of the DataSource which provides the required tables.
attribute data-source-ref {xsd:string} attribute data-source-ref {xsd:string}

View File

@ -66,7 +66,14 @@
<xs:attributeGroup name="ref"> <xs:attributeGroup name="ref">
<xs:attribute name="ref" use="required" type="xs:string"> <xs:attribute name="ref" use="required" type="xs:string">
<xs:annotation> <xs:annotation>
<xs:documentation>Defines a reference to a Spring bean id.</xs:documentation> <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="user-service-ref">
<xs:attribute name="user-service-ref" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
@ -80,7 +87,7 @@
</xs:sequence> </xs:sequence>
<xs:attribute name="ref" type="xs:string"> <xs:attribute name="ref" type="xs:string">
<xs:annotation> <xs:annotation>
<xs:documentation>Defines a reference to a Spring bean id.</xs:documentation> <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
<xs:attribute name="hash"> <xs:attribute name="hash">
@ -258,6 +265,7 @@
<xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="security:intercept-url"/> <xs:element ref="security:intercept-url"/>
<xs:element ref="security:form-login"/> <xs:element ref="security:form-login"/>
<xs:element ref="security:x509"/>
<xs:element ref="security:http-basic"/> <xs:element ref="security:http-basic"/>
<xs:element ref="security:logout"/> <xs:element ref="security:logout"/>
<xs:element ref="security:concurrent-session-control"/> <xs:element ref="security:concurrent-session-control"/>
@ -539,6 +547,48 @@
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
<xs:element name="port-mappings">
<xs:annotation>
<xs:documentation>Defines the list of mappings between http and https ports for use in redirects</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="port-mapping">
<xs:complexType>
<xs:attributeGroup ref="security:http-port"/>
<xs:attributeGroup ref="security:https-port"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="http-port">
<xs:attribute name="http" use="required" type="xs:integer"/>
</xs:attributeGroup>
<xs:attributeGroup name="https-port">
<xs:attribute name="https" use="required" type="xs:integer"/>
</xs:attributeGroup>
<xs:element name="x509">
<xs:annotation>
<xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="security:x509.attlist"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="x509.attlist">
<xs:attribute name="subject-regex-match" type="xs:string">
<xs:annotation>
<xs:documentation>The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="user-service-ref" type="xs:string">
<xs:annotation>
<xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="authentication-provider"> <xs:element name="authentication-provider">
<xs:annotation> <xs:annotation>
<xs:documentation>Indicates that the contained user-service should be used as an authentication source. </xs:documentation> <xs:documentation>Indicates that the contained user-service should be used as an authentication source. </xs:documentation>
@ -557,7 +607,7 @@
<xs:attributeGroup name="ap.attlist"> <xs:attributeGroup name="ap.attlist">
<xs:attribute name="user-service-ref" type="xs:string"> <xs:attribute name="user-service-ref" type="xs:string">
<xs:annotation> <xs:annotation>
<xs:documentation>Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data. </xs:documentation> <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
@ -608,28 +658,6 @@
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
<xs:element name="port-mappings">
<xs:annotation>
<xs:documentation>Defines the list of mappings between http and https ports for use in redirects</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="port-mapping">
<xs:complexType>
<xs:attributeGroup ref="security:http-port"/>
<xs:attributeGroup ref="security:https-port"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="http-port">
<xs:attribute name="http" use="required" type="xs:integer"/>
</xs:attributeGroup>
<xs:attributeGroup name="https-port">
<xs:attribute name="https" use="required" type="xs:integer"/>
</xs:attributeGroup>
<xs:element name="jdbc-user-service"> <xs:element name="jdbc-user-service">
<xs:annotation> <xs:annotation>
<xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation> <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>

View File

@ -6,6 +6,7 @@ import org.springframework.security.intercept.web.FilterInvocationDefinitionSour
import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.security.intercept.web.FilterInvocation;
import org.springframework.security.securechannel.ChannelProcessingFilter; import org.springframework.security.securechannel.ChannelProcessingFilter;
import org.springframework.security.ui.ExceptionTranslationFilter; import org.springframework.security.ui.ExceptionTranslationFilter;
import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter;
import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilter;
import org.springframework.security.ui.logout.LogoutFilter; import org.springframework.security.ui.logout.LogoutFilter;
import org.springframework.security.ui.rememberme.RememberMeProcessingFilter; import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
@ -222,6 +223,17 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(rememberMeServices instanceof PersistentTokenBasedRememberMeServices); assertTrue(rememberMeServices instanceof PersistentTokenBasedRememberMeServices);
} }
@Test
public void x509SupportAddsFilterAtExpectedPosition() throws Exception {
setContext(
"<http auto-config='true'>" +
" <x509 />" +
"</http>" + AUTH_PROVIDER_XML);
List filters = getFilterChainProxy().getFilters("/someurl");
assertTrue(filters.get(2) instanceof X509PreAuthenticatedProcessingFilter);
}
private void setContext(String context) { private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context); appContext = new InMemoryXmlApplicationContext(context);
} }

View File

@ -22,8 +22,11 @@
<intercept-url pattern="/post.html" access="ROLE_TELLER" /> <intercept-url pattern="/post.html" access="ROLE_TELLER" />
--> -->
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<!--
<!-- All of this is unnecessary if auto-config="true" --> Uncomment to enable X509 client authentication support
<x509 />
-->
<!-- All of this is unnecessary if auto-config="true" -->
<form-login /> <form-login />
<anonymous /> <anonymous />
<http-basic /> <http-basic />
@ -33,6 +36,8 @@
<concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/> <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
</http> </http>
<!--
Uncomment to add X509 support as an external filter definition (an alternative to the <x509 /> element).
<beans:bean id="x509Filter" class="org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter" autowire="byType"> <beans:bean id="x509Filter" class="org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter" autowire="byType">
<custom-filter after="X509_FILTER"/> <custom-filter after="X509_FILTER"/>
@ -44,7 +49,7 @@
<beans:bean class="org.springframework.security.providers.preauth.UserDetailsByNameServiceWrapper" autowire="byType"/> <beans:bean class="org.springframework.security.providers.preauth.UserDetailsByNameServiceWrapper" autowire="byType"/>
</beans:property> </beans:property>
</beans:bean> </beans:bean>
-->
<!-- <!--
Usernames/Passwords are Usernames/Passwords are
rod/koala rod/koala