diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java index 4eb5608b65..6e58c1f22a 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java @@ -34,11 +34,13 @@ import org.springframework.util.Assert; * distinguished name and a set of attributes that have been retrieved from the Ldap server. *

* An instance may be created as the result of a search, or when user information is retrieved during authentication. - *

*

* An instance of this class will be used by the LdapAuthenticationProvider to construct the final user details * object that it returns. - *

+ *

+ * The {@code equals} and {@code hashcode} methods are implemented using the {@code Dn} property and do not consider + * additional state, so it is not possible two store two instances with the same DN in the same set, or use them as + * keys in a map. * * @author Luke Taylor */ @@ -104,14 +106,28 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData return graceLoginsRemaining; } + @Override + public boolean equals(Object obj) { + if (obj instanceof LdapUserDetailsImpl) { + return dn.equals(((LdapUserDetailsImpl)obj).dn); + } + return false; + } + + @Override + public int hashCode() { + return dn.hashCode(); + } + public String toString() { StringBuilder sb = new StringBuilder(); sb.append(super.toString()).append(": "); + sb.append("Dn: ").append(dn).append("; "); sb.append("Username: ").append(this.username).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); - sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); + sb.append("CredentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (this.getAuthorities() != null) { diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java index 8ccf3615ab..4255ba5b3d 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java @@ -1,16 +1,20 @@ package org.springframework.security.ldap.userdetails; -import junit.framework.TestCase; +import static org.junit.Assert.*; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; -import org.springframework.security.ldap.userdetails.InetOrgPerson; /** * @author Luke Taylor */ -public class InetOrgPersonTests extends TestCase { +public class InetOrgPersonTests { + @Test public void testUsernameIsMappedFromContextUidIfNotSet() { InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext()); InetOrgPerson p = (InetOrgPerson) essence.createUserDetails(); @@ -18,7 +22,19 @@ public class InetOrgPersonTests extends TestCase { assertEquals("ghengis", p.getUsername()); } - public void testUsernameIsDifferentFromContextUidIfSet() { + @Test + public void hashLookupViaEqualObjectRetrievesOriginal() throws Exception { + InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext()); + InetOrgPerson p = (InetOrgPerson) essence.createUserDetails(); + essence = new InetOrgPerson.Essence(createUserContext()); + InetOrgPerson p2 = (InetOrgPerson) essence.createUserDetails(); + Set set = new HashSet(); + set.add(p); + assertTrue(set.contains(p2)); + } + + @Test + public void usernameIsDifferentFromContextUidIfSet() { InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext()); essence.setUsername("joe"); InetOrgPerson p = (InetOrgPerson) essence.createUserDetails(); @@ -27,7 +43,8 @@ public class InetOrgPersonTests extends TestCase { assertEquals("ghengis", p.getUid()); } - public void testAttributesMapCorrectlyFromContext() { + @Test + public void attributesMapCorrectlyFromContext() { InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext()); InetOrgPerson p = (InetOrgPerson) essence.createUserDetails(); @@ -50,6 +67,7 @@ public class InetOrgPersonTests extends TestCase { assertEquals("G", p.getInitials()); } + @Test public void testPasswordIsSetFromContextUserPassword() { InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext()); InetOrgPerson p = (InetOrgPerson) essence.createUserDetails(); @@ -57,7 +75,8 @@ public class InetOrgPersonTests extends TestCase { assertEquals("pillage", p.getPassword()); } - public void testMappingBackToContextMatchesOriginalData() { + @Test + public void mappingBackToContextMatchesOriginalData() { DirContextAdapter ctx1 = createUserContext(); DirContextAdapter ctx2 = new DirContextAdapter(); ctx1.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"}); @@ -68,7 +87,8 @@ public class InetOrgPersonTests extends TestCase { assertEquals(ctx1, ctx2); } - public void testCopyMatchesOriginalData() { + @Test + public void copyMatchesOriginalData() { DirContextAdapter ctx1 = createUserContext(); DirContextAdapter ctx2 = new DirContextAdapter(); ctx2.setDn(new DistinguishedName("ignored=ignored"));