mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-23 20:42:14 +00:00
SEC-2122: Update namespace to support bcrypt.
password-encoder now supports hash='bcrypt'.
This commit is contained in:
parent
896339087f
commit
ebba8ac514
@ -19,6 +19,7 @@ import org.springframework.security.authentication.encoding.PasswordEncoder;
|
|||||||
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
||||||
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
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;
|
||||||
@ -34,6 +35,7 @@ public class PasswordEncoderParser {
|
|||||||
static final String ATT_REF = "ref";
|
static final String ATT_REF = "ref";
|
||||||
public static final String ATT_HASH = "hash";
|
public static final String ATT_HASH = "hash";
|
||||||
static final String ATT_BASE_64 = "base64";
|
static final String ATT_BASE_64 = "base64";
|
||||||
|
static final String OPT_HASH_BCRYPT = "bcrypt";
|
||||||
static final String OPT_HASH_PLAINTEXT = "plaintext";
|
static final String OPT_HASH_PLAINTEXT = "plaintext";
|
||||||
static final String OPT_HASH_SHA = "sha";
|
static final String OPT_HASH_SHA = "sha";
|
||||||
static final String OPT_HASH_SHA256 = "sha-256";
|
static final String OPT_HASH_SHA256 = "sha-256";
|
||||||
@ -42,11 +44,12 @@ public class PasswordEncoderParser {
|
|||||||
static final String OPT_HASH_LDAP_SHA = "{sha}";
|
static final String OPT_HASH_LDAP_SHA = "{sha}";
|
||||||
static final String OPT_HASH_LDAP_SSHA = "{ssha}";
|
static final String OPT_HASH_LDAP_SSHA = "{ssha}";
|
||||||
|
|
||||||
private static final Map<String, Class<? extends PasswordEncoder>> ENCODER_CLASSES;
|
private static final Map<String, Class<?>> ENCODER_CLASSES;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ENCODER_CLASSES = new HashMap<String, Class<? extends PasswordEncoder>>();
|
ENCODER_CLASSES = new HashMap<String, Class<?>>();
|
||||||
ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class);
|
ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class);
|
||||||
|
ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class);
|
||||||
ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class);
|
ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class);
|
||||||
ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class);
|
ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class);
|
||||||
ENCODER_CLASSES.put(OPT_HASH_MD4, Md4PasswordEncoder.class);
|
ENCODER_CLASSES.put(OPT_HASH_MD4, Md4PasswordEncoder.class);
|
||||||
@ -84,12 +87,17 @@ public class PasswordEncoderParser {
|
|||||||
Element saltSourceElt = DomUtils.getChildElementByTagName(element, Elements.SALT_SOURCE);
|
Element saltSourceElt = DomUtils.getChildElementByTagName(element, Elements.SALT_SOURCE);
|
||||||
|
|
||||||
if (saltSourceElt != null) {
|
if (saltSourceElt != null) {
|
||||||
|
if (OPT_HASH_BCRYPT.equals(hash)) {
|
||||||
|
parserContext.getReaderContext().error(Elements.SALT_SOURCE + " isn't compatible with bcrypt",
|
||||||
|
parserContext.extractSource(saltSourceElt));
|
||||||
|
} else {
|
||||||
saltSource = new SaltSourceBeanDefinitionParser().parse(saltSourceElt, parserContext);
|
saltSource = new SaltSourceBeanDefinitionParser().parse(saltSourceElt, parserContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static BeanDefinition createPasswordEncoderBeanDefinition(String hash, boolean useBase64) {
|
public static BeanDefinition createPasswordEncoderBeanDefinition(String hash, boolean useBase64) {
|
||||||
Class<? extends PasswordEncoder> beanClass = ENCODER_CLASSES.get(hash);
|
Class<?> beanClass = ENCODER_CLASSES.get(hash);
|
||||||
BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder.rootBeanDefinition(beanClass);
|
BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder.rootBeanDefinition(beanClass);
|
||||||
|
|
||||||
if (OPT_HASH_SHA256.equals(hash)) {
|
if (OPT_HASH_SHA256.equals(hash)) {
|
||||||
|
@ -6,8 +6,8 @@ default namespace = "http://www.springframework.org/schema/security"
|
|||||||
start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider
|
start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider
|
||||||
|
|
||||||
hash =
|
hash =
|
||||||
## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
|
## Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
|
||||||
attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
|
attribute hash {"bcrypt" | "plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
|
||||||
base64 =
|
base64 =
|
||||||
## Whether a string should be base64 encoded
|
## Whether a string should be base64 encoded
|
||||||
attribute base64 {xsd:boolean}
|
attribute base64 {xsd:boolean}
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
<xs:attributeGroup name="hash">
|
<xs:attributeGroup name="hash">
|
||||||
<xs:attribute name="hash" use="required">
|
<xs:attribute name="hash" use="required">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using
|
<xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
|
||||||
MD4, as it is a very weak hashing algorithm.
|
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="bcrypt"/>
|
||||||
<xs:enumeration value="plaintext"/>
|
<xs:enumeration value="plaintext"/>
|
||||||
<xs:enumeration value="sha"/>
|
<xs:enumeration value="sha"/>
|
||||||
<xs:enumeration value="sha-256"/>
|
<xs:enumeration value="sha-256"/>
|
||||||
@ -154,12 +154,12 @@
|
|||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
<xs:attribute name="hash">
|
<xs:attribute name="hash">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using
|
<xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
|
||||||
MD4, as it is a very weak hashing algorithm.
|
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="bcrypt"/>
|
||||||
<xs:enumeration value="plaintext"/>
|
<xs:enumeration value="plaintext"/>
|
||||||
<xs:enumeration value="sha"/>
|
<xs:enumeration value="sha"/>
|
||||||
<xs:enumeration value="sha-256"/>
|
<xs:enumeration value="sha-256"/>
|
||||||
@ -537,12 +537,12 @@
|
|||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
<xs:attribute name="hash">
|
<xs:attribute name="hash">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using
|
<xs:documentation>Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
|
||||||
MD4, as it is a very weak hashing algorithm.
|
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="bcrypt"/>
|
||||||
<xs:enumeration value="plaintext"/>
|
<xs:enumeration value="plaintext"/>
|
||||||
<xs:enumeration value="sha"/>
|
<xs:enumeration value="sha"/>
|
||||||
<xs:enumeration value="sha-256"/>
|
<xs:enumeration value="sha-256"/>
|
||||||
|
@ -57,6 +57,35 @@ public class AuthenticationProviderBeanDefinitionParserTests {
|
|||||||
getProvider().authenticate(bob);
|
getProvider().authenticate(bob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void providerWithBCryptPasswordEncoderWorks() throws Exception {
|
||||||
|
setContext(" <authentication-provider>" +
|
||||||
|
" <password-encoder hash='bcrypt'/>" +
|
||||||
|
" <user-service>" +
|
||||||
|
" <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />" +
|
||||||
|
" </user-service>" +
|
||||||
|
" </authentication-provider>");
|
||||||
|
|
||||||
|
getProvider().authenticate(bob);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=BeanDefinitionParsingException.class)
|
||||||
|
public void bCryptAndSaltSourceRaisesException() throws Exception {
|
||||||
|
appContext = new InMemoryXmlApplicationContext("" +
|
||||||
|
" <authentication-manager>" +
|
||||||
|
" <authentication-provider>" +
|
||||||
|
" <password-encoder hash='bcrypt'>" +
|
||||||
|
" <salt-source ref='saltSource'/>" +
|
||||||
|
" </password-encoder>" +
|
||||||
|
" <user-service>" +
|
||||||
|
" <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />" +
|
||||||
|
" </user-service>" +
|
||||||
|
" </authentication-provider>" +
|
||||||
|
" </authentication-manager>" +
|
||||||
|
" <b:bean id='saltSource' class='" + ReflectionSaltSource.class.getName() +"'>" +
|
||||||
|
" <b:property name='userPropertyToUse' value='username'/>" +
|
||||||
|
" </b:bean>");
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
public void providerWithMd5PasswordEncoderWorks() throws Exception {
|
public void providerWithMd5PasswordEncoderWorks() throws Exception {
|
||||||
setContext(" <authentication-provider>" +
|
setContext(" <authentication-provider>" +
|
||||||
|
@ -14,6 +14,7 @@ Import-Template:
|
|||||||
org.springframework.security.access.*;version="${secRange}",
|
org.springframework.security.access.*;version="${secRange}",
|
||||||
org.springframework.security.authentication.*;version="${secRange}",
|
org.springframework.security.authentication.*;version="${secRange}",
|
||||||
org.springframework.security.core.*;version="${secRange}",
|
org.springframework.security.core.*;version="${secRange}",
|
||||||
|
org.springframework.security.crypto.bcrypt.*;version="${secRange}",
|
||||||
org.springframework.security.util;version="${secRange}",
|
org.springframework.security.util;version="${secRange}",
|
||||||
org.springframework.security.provisioning;version="${secRange}",
|
org.springframework.security.provisioning;version="${secRange}",
|
||||||
org.springframework.security.web.*;version="${secRange}";resolution:=optional,
|
org.springframework.security.web.*;version="${secRange}";resolution:=optional,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user