SEC-560: Removed local password comparison form PasswordComparisonAuthenticator.
This commit is contained in:
parent
0e1ae11fca
commit
88e01624eb
|
@ -35,7 +35,7 @@ import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link org.springframework.security.providers.ldap.LdapAuthenticator LdapAuthenticator} which compares the login
|
* An {@link org.springframework.security.providers.ldap.LdapAuthenticator LdapAuthenticator} which compares the login
|
||||||
* password with the value stored in the directory.
|
* password with the value stored in the directory using an LDAP "compare" operation.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This can be achieved either by retrieving the password attribute for the user and comparing it locally,
|
* This can be achieved either by retrieving the password attribute for the user and comparing it locally,
|
||||||
|
@ -98,20 +98,9 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
|
||||||
throw new UsernameNotFoundException(username);
|
throw new UsernameNotFoundException(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object retrievedPassword = user.getObjectAttribute(passwordAttributeName);
|
|
||||||
|
|
||||||
if (retrievedPassword != null) {
|
|
||||||
if (!verifyPassword(password, retrievedPassword)) {
|
|
||||||
throw new BadCredentialsException(messages.getMessage(
|
|
||||||
"PasswordComparisonAuthenticator.badCredentials", "Bad credentials"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Password attribute wasn't retrieved for user '" + authentication
|
logger.debug("Performing LDAP compare of password attribute '" + passwordAttributeName + "' for user '" +
|
||||||
+ "'. Performing LDAP compare of password attribute '" + passwordAttributeName + "'");
|
user.getDn() +"'");
|
||||||
}
|
}
|
||||||
|
|
||||||
String encodedPassword = passwordEncoder.encodePassword(password, null);
|
String encodedPassword = passwordEncoder.encodePassword(password, null);
|
||||||
|
@ -134,29 +123,4 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
|
||||||
Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
|
Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the use of both simple and hashed passwords in the directory.
|
|
||||||
*
|
|
||||||
* @param password the password supplied by the user
|
|
||||||
* @param ldapPassword the (possibly hashed) password (from the directory)
|
|
||||||
*
|
|
||||||
* @return true if they match
|
|
||||||
*/
|
|
||||||
protected boolean verifyPassword(String password, Object ldapPassword) {
|
|
||||||
if (!(ldapPassword instanceof String)) {
|
|
||||||
// Assume it's binary
|
|
||||||
ldapPassword = new String((byte[]) ldapPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ldapPassword.equals(password)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passwordEncoder.isPasswordValid((String)ldapPassword, password, null)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
public void onSetUp() throws Exception {
|
public void onSetUp() throws Exception {
|
||||||
super.onSetUp();
|
super.onSetUp();
|
||||||
authenticator = new PasswordComparisonAuthenticator(getContextSource());
|
authenticator = new PasswordComparisonAuthenticator(getContextSource());
|
||||||
|
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
||||||
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
||||||
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
|
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
|
||||||
ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
|
ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
|
||||||
|
@ -74,38 +75,11 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
} catch (UsernameNotFoundException expected) {}
|
} catch (UsernameNotFoundException expected) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = BadCredentialsException.class)
|
||||||
public void testLocalComparisonSucceedsWithShaEncodedPassword() {
|
|
||||||
// Ben's password is SHA encoded
|
|
||||||
authenticator.authenticate(ben);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocalPasswordComparisonFailsWithWrongPassword() {
|
|
||||||
try {
|
|
||||||
authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", "wrongpass"));
|
|
||||||
fail("Authentication should fail with wrong password.");
|
|
||||||
} catch (BadCredentialsException expected) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLdapPasswordCompareFailsWithWrongPassword() {
|
public void testLdapPasswordCompareFailsWithWrongPassword() {
|
||||||
// Don't retrieve the password
|
// Don't retrieve the password
|
||||||
authenticator.setUserAttributes(new String[] {"uid", "cn", "sn"});
|
authenticator.setUserAttributes(new String[] {"uid", "cn", "sn"});
|
||||||
try {
|
authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", "wrongpass"));
|
||||||
authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", "wrongpass"));
|
|
||||||
fail("Authentication should fail with wrong password.");
|
|
||||||
} catch(BadCredentialsException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocalPasswordComparisonSucceedsWithCorrectPassword() {
|
|
||||||
DirContextOperations user = authenticator.authenticate(bob);
|
|
||||||
// check username is retrieved.
|
|
||||||
assertEquals("bob", user.getStringAttribute("uid"));
|
|
||||||
String password = new String((byte[])user.getObjectAttribute("userPassword"));
|
|
||||||
assertEquals("bobspassword", password);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -117,7 +91,6 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
@Test
|
@Test
|
||||||
public void testOnlySpecifiedAttributesAreRetrieved() throws Exception {
|
public void testOnlySpecifiedAttributesAreRetrieved() throws Exception {
|
||||||
authenticator.setUserAttributes(new String[] {"uid", "userPassword"});
|
authenticator.setUserAttributes(new String[] {"uid", "userPassword"});
|
||||||
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
|
||||||
|
|
||||||
DirContextAdapter user = (DirContextAdapter) authenticator.authenticate(bob);
|
DirContextAdapter user = (DirContextAdapter) authenticator.authenticate(bob);
|
||||||
assertEquals("Should have retrieved 2 attribute (uid, userPassword)", 2, user.getAttributes().size());
|
assertEquals("Should have retrieved 2 attribute (uid, userPassword)", 2, user.getAttributes().size());
|
||||||
|
@ -127,8 +100,6 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
public void testLdapCompareSucceedsWithCorrectPassword() {
|
public void testLdapCompareSucceedsWithCorrectPassword() {
|
||||||
// Don't retrieve the password
|
// Don't retrieve the password
|
||||||
authenticator.setUserAttributes(new String[] {"uid"});
|
authenticator.setUserAttributes(new String[] {"uid"});
|
||||||
// Bob has a plaintext password.
|
|
||||||
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
|
||||||
authenticator.authenticate(bob);
|
authenticator.authenticate(bob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,15 +107,13 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
public void testLdapCompareSucceedsWithShaEncodedPassword() {
|
public void testLdapCompareSucceedsWithShaEncodedPassword() {
|
||||||
// Don't retrieve the password
|
// Don't retrieve the password
|
||||||
authenticator.setUserAttributes(new String[] {"uid"});
|
authenticator.setUserAttributes(new String[] {"uid"});
|
||||||
|
authenticator.setPasswordEncoder(new LdapShaPasswordEncoder());
|
||||||
authenticator.authenticate(ben);
|
authenticator.authenticate(ben);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testPasswordEncoderCantBeNull() {
|
public void testPasswordEncoderCantBeNull() {
|
||||||
try {
|
authenticator.setPasswordEncoder(null);
|
||||||
authenticator.setPasswordEncoder(null);
|
|
||||||
fail("Password encoder can't be null");
|
|
||||||
} catch (IllegalArgumentException expected) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -156,7 +125,6 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
@Test
|
@Test
|
||||||
public void testLdapCompareWithDifferentPasswordAttributeSucceeds() {
|
public void testLdapCompareWithDifferentPasswordAttributeSucceeds() {
|
||||||
authenticator.setUserAttributes(new String[] {"uid"});
|
authenticator.setUserAttributes(new String[] {"uid"});
|
||||||
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
|
||||||
authenticator.setPasswordAttributeName("cn");
|
authenticator.setPasswordAttributeName("cn");
|
||||||
authenticator.authenticate(new UsernamePasswordAuthenticationToken("ben", "Ben Alex"));
|
authenticator.authenticate(new UsernamePasswordAuthenticationToken("ben", "Ben Alex"));
|
||||||
}
|
}
|
||||||
|
@ -164,9 +132,10 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
|
||||||
@Test
|
@Test
|
||||||
public void testWithUserSearch() {
|
public void testWithUserSearch() {
|
||||||
authenticator = new PasswordComparisonAuthenticator(getContextSource());
|
authenticator = new PasswordComparisonAuthenticator(getContextSource());
|
||||||
|
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
||||||
assertTrue("User DN matches shouldn't be available", authenticator.getUserDns("Bob").isEmpty());
|
assertTrue("User DN matches shouldn't be available", authenticator.getUserDns("Bob").isEmpty());
|
||||||
|
|
||||||
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=Bob,ou=people,dc=springframework,dc=org"));
|
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=Bob,ou=people"));
|
||||||
ctx.setAttributeValue("userPassword", "bobspassword");
|
ctx.setAttributeValue("userPassword", "bobspassword");
|
||||||
|
|
||||||
authenticator.setUserSearch(new MockUserSearch(ctx));
|
authenticator.setUserSearch(new MockUserSearch(ctx));
|
||||||
|
|
Loading…
Reference in New Issue