SEC-1018: Changes to allow external reference to SaltSource bean from the namespace.
This commit is contained in:
parent
00125cddee
commit
171456a26c
|
@ -1,26 +1,24 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.security.providers.encoding.BaseDigestPasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.Md4PasswordEncoder;
|
import org.springframework.security.providers.encoding.Md4PasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
|
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.PasswordEncoder;
|
import org.springframework.security.providers.encoding.PasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.PlaintextPasswordEncoder;
|
import org.springframework.security.providers.encoding.PlaintextPasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.ShaPasswordEncoder;
|
import org.springframework.security.providers.encoding.ShaPasswordEncoder;
|
||||||
import org.springframework.security.providers.encoding.BaseDigestPasswordEncoder;
|
|
||||||
import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder;
|
import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder;
|
||||||
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.RootBeanDefinition;
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
|
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stateful parser for the <password-encoder> element.
|
* Stateful parser for the <password-encoder> element.
|
||||||
|
@ -30,7 +28,7 @@ import java.util.HashMap;
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class PasswordEncoderParser {
|
class PasswordEncoderParser {
|
||||||
static final String ATT_REF = "ref";
|
static final String ATT_REF = "ref";
|
||||||
static final String ATT_HASH = "hash";
|
static final String ATT_HASH = "hash";
|
||||||
static final String ATT_BASE_64 = "base64";
|
static final String ATT_BASE_64 = "base64";
|
||||||
|
@ -56,7 +54,7 @@ public class PasswordEncoderParser {
|
||||||
private Log logger = LogFactory.getLog(getClass());
|
private Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private BeanMetadataElement passwordEncoder;
|
private BeanMetadataElement passwordEncoder;
|
||||||
private BeanDefinition saltSource;
|
private BeanMetadataElement saltSource;
|
||||||
|
|
||||||
public PasswordEncoderParser(Element element, ParserContext parserContext) {
|
public PasswordEncoderParser(Element element, ParserContext parserContext) {
|
||||||
parse(element, parserContext);
|
parse(element, parserContext);
|
||||||
|
@ -104,7 +102,7 @@ public class PasswordEncoderParser {
|
||||||
return passwordEncoder;
|
return passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BeanDefinition getSaltSource() {
|
public BeanMetadataElement getSaltSource() {
|
||||||
return saltSource;
|
return saltSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.providers.dao.salt.ReflectionSaltSource;
|
import org.springframework.security.providers.dao.salt.ReflectionSaltSource;
|
||||||
import org.springframework.security.providers.dao.salt.SystemWideSaltSource;
|
import org.springframework.security.providers.dao.salt.SystemWideSaltSource;
|
||||||
|
@ -14,20 +15,27 @@ import org.w3c.dom.Element;
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class SaltSourceBeanDefinitionParser implements BeanDefinitionParser {
|
class SaltSourceBeanDefinitionParser {
|
||||||
static final String ATT_USER_PROPERTY = "user-property";
|
private static final String ATT_USER_PROPERTY = "user-property";
|
||||||
static final String ATT_SYSTEM_WIDE = "system-wide";
|
private static final String ATT_REF = "ref";
|
||||||
|
private static final String ATT_SYSTEM_WIDE = "system-wide";
|
||||||
|
|
||||||
|
public BeanMetadataElement parse(Element element, ParserContext parserContext) {
|
||||||
|
String ref = element.getAttribute(ATT_REF);
|
||||||
|
|
||||||
|
if (StringUtils.hasText(ref)) {
|
||||||
|
return new RuntimeBeanReference(ref);
|
||||||
|
}
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
|
||||||
RootBeanDefinition saltSource;
|
|
||||||
String userProperty = element.getAttribute(ATT_USER_PROPERTY);
|
String userProperty = element.getAttribute(ATT_USER_PROPERTY);
|
||||||
|
RootBeanDefinition saltSource;
|
||||||
|
|
||||||
if (StringUtils.hasText(userProperty)) {
|
if (StringUtils.hasText(userProperty)) {
|
||||||
saltSource = new RootBeanDefinition(ReflectionSaltSource.class);
|
saltSource = new RootBeanDefinition(ReflectionSaltSource.class);
|
||||||
saltSource.getPropertyValues().addPropertyValue("userPropertyToUse", userProperty);
|
saltSource.getPropertyValues().addPropertyValue("userPropertyToUse", userProperty);
|
||||||
saltSource.setSource(parserContext.extractSource(element));
|
saltSource.setSource(parserContext.extractSource(element));
|
||||||
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
|
|
||||||
return saltSource;
|
return saltSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ password-encoder.attlist &=
|
||||||
|
|
||||||
salt-source =
|
salt-source =
|
||||||
## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
|
## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
|
||||||
element salt-source {user-property | system-wide}
|
element salt-source {user-property | system-wide | ref}
|
||||||
user-property =
|
user-property =
|
||||||
## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
|
## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
|
||||||
attribute user-property {xsd:string}
|
attribute user-property {xsd:string}
|
||||||
|
|
|
@ -419,6 +419,12 @@
|
||||||
salt for a password encoder. </xs:documentation>
|
salt for a password encoder. </xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
|
<xs:attribute name="ref" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Defines a reference to a Spring bean
|
||||||
|
Id.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
@ -1331,6 +1337,12 @@
|
||||||
a password encoder. </xs:documentation>
|
a password encoder. </xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
|
<xs:attribute name="ref" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Defines a reference to a Spring bean
|
||||||
|
Id.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class AuthenticationProviderBeanDefinitionParserTests {
|
||||||
ShaPasswordEncoder encoder = (ShaPasswordEncoder) FieldUtils.getFieldValue(getProvider(), "passwordEncoder");
|
ShaPasswordEncoder encoder = (ShaPasswordEncoder) FieldUtils.getFieldValue(getProvider(), "passwordEncoder");
|
||||||
assertEquals("SHA-256", encoder.getAlgorithm());
|
assertEquals("SHA-256", encoder.getAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void passwordIsBase64EncodedWhenBase64IsEnabled() throws Exception {
|
public void passwordIsBase64EncodedWhenBase64IsEnabled() throws Exception {
|
||||||
setContext(" <authentication-provider>" +
|
setContext(" <authentication-provider>" +
|
||||||
|
@ -99,18 +99,21 @@ public class AuthenticationProviderBeanDefinitionParserTests {
|
||||||
|
|
||||||
getProvider().authenticate(bob);
|
getProvider().authenticate(bob);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void externalUserServiceAndPasswordEncoderWork() throws Exception {
|
public void externalUserServicePasswordEncoderAndSaltSourceWork() throws Exception {
|
||||||
setContext(" <authentication-provider user-service-ref='customUserService'>" +
|
setContext(" <authentication-provider user-service-ref='customUserService'>" +
|
||||||
" <password-encoder ref='customPasswordEncoder'>" +
|
" <password-encoder ref='customPasswordEncoder'>" +
|
||||||
" <salt-source user-property='username'/>" +
|
" <salt-source ref='saltSource'/>" +
|
||||||
" </password-encoder>" +
|
" </password-encoder>" +
|
||||||
" </authentication-provider>" +
|
" </authentication-provider>" +
|
||||||
|
|
||||||
" <b:bean id='customPasswordEncoder' " +
|
" <b:bean id='customPasswordEncoder' " +
|
||||||
"class='org.springframework.security.providers.encoding.Md5PasswordEncoder'/>" +
|
"class='org.springframework.security.providers.encoding.Md5PasswordEncoder'/>" +
|
||||||
|
" <b:bean id='saltSource' " +
|
||||||
|
" class='org.springframework.security.providers.dao.salt.ReflectionSaltSource'>" +
|
||||||
|
" <b:property name='userPropertyToUse' value='username'/>" +
|
||||||
|
" </b:bean>" +
|
||||||
" <b:bean id='customUserService' " +
|
" <b:bean id='customUserService' " +
|
||||||
" class='org.springframework.security.userdetails.memory.InMemoryDaoImpl'>" +
|
" class='org.springframework.security.userdetails.memory.InMemoryDaoImpl'>" +
|
||||||
" <b:property name='userMap' value='bob=f117f0862384e9497ff4f470e3522606,ROLE_A'/>" +
|
" <b:property name='userMap' value='bob=f117f0862384e9497ff4f470e3522606,ROLE_A'/>" +
|
||||||
|
|
Loading…
Reference in New Issue