From 6eb17c85469ee29f812bcb2a0470686011908dd5 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Mon, 10 Sep 2007 21:13:45 +0000 Subject: [PATCH] SEC-513: Ldap user manager implementation classes changed to use new spring ldap apis. --- .../userdetails/ldap/InetOrgPerson.java | 5 +- .../ldap/InetOrgPersonContextMapper.java | 4 +- .../userdetails/ldap/LdapUserDetailsImpl.java | 3 +- .../ldap/LdapUserDetailsManager.java | 49 +++++++----- .../ldap/LdapUserDetailsMapper.java | 9 +-- .../userdetails/ldap/Person.java | 7 +- .../userdetails/ldap/PersonContextMapper.java | 4 +- .../ldap/UserDetailsContextMapper.java | 4 +- .../userdetails/ldap/InetOrgPersonTests.java | 5 +- .../ldap/LdapUserDetailsManagerTests.java | 75 +++++++++++-------- .../ldap/LdapUserDetailsMapperTests.java | 5 +- 11 files changed, 97 insertions(+), 73 deletions(-) diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPerson.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPerson.java index e6c06bc477..fcd687b508 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPerson.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPerson.java @@ -14,8 +14,9 @@ */ package org.acegisecurity.userdetails.ldap; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; + /** * UserDetails implementation whose properties are based on a subset of the diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPersonContextMapper.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPersonContextMapper.java index 474b4081bb..7ca1ab9ad5 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPersonContextMapper.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPersonContextMapper.java @@ -16,8 +16,8 @@ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.GrantedAuthority; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DirContextAdapter; import org.springframework.util.Assert; diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java index ca372ac790..7c0bb6d075 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java @@ -18,8 +18,7 @@ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.GrantedAuthority; import org.springframework.util.Assert; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; import java.util.ArrayList; import java.util.Arrays; diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManager.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManager.java index f1389eddf9..8e460ef4d1 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManager.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManager.java @@ -21,23 +21,34 @@ import org.acegisecurity.ldap.LdapUtils; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.Authentication; +import org.acegisecurity.BadCredentialsException; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; -import org.springframework.ldap.support.DistinguishedName; -import org.springframework.ldap.support.DirContextAdapter; -import org.springframework.ldap.LdapTemplate; -import org.springframework.ldap.AttributesMapper; -import org.springframework.ldap.ContextSource; -import org.springframework.ldap.ContextExecutor; -import org.springframework.ldap.SearchExecutor; -import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.AttributesMapper; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.ContextExecutor; +import org.springframework.ldap.core.SearchExecutor; +import org.springframework.ldap.core.AttributesMapperCallbackHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.naming.*; import javax.naming.ldap.LdapContext; -import javax.naming.directory.*; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.directory.Attributes; +import javax.naming.directory.Attribute; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.SearchControls; + import java.util.*; /** @@ -150,9 +161,6 @@ public class LdapUserDetailsManager implements UserDetailsManager { String username = authentication.getName(); - - - logger.debug("Changing password for user '"+ username); final DistinguishedName dn = buildDn(username); @@ -172,7 +180,11 @@ public class LdapUserDetailsManager implements UserDetailsManager { ctx.removeFromEnvironment("com.sun.jndi.ldap.connect.pool"); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toUrl()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword); - ctx.reconnect(null); + try { + ctx.reconnect(null); + } catch (javax.naming.AuthenticationException e) { + throw new BadCredentialsException("Authentication for password change failed."); + } ctx.modifyAttributes(dn, passwordChange); @@ -199,8 +211,8 @@ public class LdapUserDetailsManager implements UserDetailsManager { } }; - LdapTemplate.AttributesMapperCallbackHandler roleCollector = - template.new AttributesMapperCallbackHandler(roleMapper); + AttributesMapperCallbackHandler roleCollector = + new AttributesMapperCallbackHandler(roleMapper); template.search(se, roleCollector); List authorities = roleCollector.getList(); @@ -277,7 +289,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { LdapUtils.closeContext((Context) obj); } return true; - } catch(EntryNotFoundException e) { + } catch(org.springframework.ldap.NameNotFoundException e) { return false; } } @@ -402,13 +414,14 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** * This class allows us to set the updateMode property of DirContextAdapter when updating existing users. + * TODO: No longer needed as of Ldap 1.2. */ private static class UserContext extends DirContextAdapter { public UserContext(Attributes pAttrs, Name dn) { super(pAttrs, dn); } - protected void setUpdateMode(boolean mode) { + public void setUpdateMode(boolean mode) { super.setUpdateMode(mode); } } diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.java index 4cf9f6bba9..98819858ad 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.java @@ -18,21 +18,16 @@ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.ldap.LdapEntryMapper; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; -import org.springframework.ldap.ContextMapper; import org.springframework.ldap.UncategorizedLdapException; -import org.springframework.ldap.AttributesIntegrityViolationException; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.DirContextAdapter; -import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; /** diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/Person.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/Person.java index a14b029996..0acfa09edb 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/Person.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/Person.java @@ -14,9 +14,12 @@ */ package org.acegisecurity.userdetails.ldap; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; + import org.springframework.util.Assert; + +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; + import org.acegisecurity.ldap.LdapUtils; import java.util.List; diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/PersonContextMapper.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/PersonContextMapper.java index a42b287c83..bdfb46aa8b 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/PersonContextMapper.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/PersonContextMapper.java @@ -2,8 +2,8 @@ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.GrantedAuthority; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DirContextAdapter; import org.springframework.util.Assert; /** diff --git a/core/src/main/java/org/acegisecurity/userdetails/ldap/UserDetailsContextMapper.java b/core/src/main/java/org/acegisecurity/userdetails/ldap/UserDetailsContextMapper.java index d9894c851e..13596d17e5 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/ldap/UserDetailsContextMapper.java +++ b/core/src/main/java/org/acegisecurity/userdetails/ldap/UserDetailsContextMapper.java @@ -16,8 +16,8 @@ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.GrantedAuthority; -import org.springframework.ldap.support.DirContextOperations; -import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DirContextAdapter; /** * Operations to map a UserDetails object to and from a Spring LDAP DirContextOperations implementation. diff --git a/core/src/test/java/org/acegisecurity/userdetails/ldap/InetOrgPersonTests.java b/core/src/test/java/org/acegisecurity/userdetails/ldap/InetOrgPersonTests.java index 7b823a6779..cab21bf8c1 100644 --- a/core/src/test/java/org/acegisecurity/userdetails/ldap/InetOrgPersonTests.java +++ b/core/src/test/java/org/acegisecurity/userdetails/ldap/InetOrgPersonTests.java @@ -1,8 +1,9 @@ package org.acegisecurity.userdetails.ldap; import junit.framework.TestCase; -import org.springframework.ldap.support.DirContextAdapter; -import org.springframework.ldap.support.DistinguishedName; + +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DistinguishedName; /** * @author Luke Taylor diff --git a/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManagerTests.java b/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManagerTests.java index be30783e27..4e302328c0 100644 --- a/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManagerTests.java +++ b/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManagerTests.java @@ -14,36 +14,32 @@ */ package org.acegisecurity.userdetails.ldap; -import org.acegisecurity.ldap.AbstractLdapServerTestCase; -import org.acegisecurity.ldap.LdapUtils; +import org.acegisecurity.ldap.SpringSecurityLdapTemplate; +import org.acegisecurity.ldap.AbstractLdapIntegrationTests; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.context.SecurityContextHolder; -import org.springframework.ldap.LdapTemplate; -import org.springframework.ldap.support.DirContextAdapter; -import org.springframework.ldap.support.DistinguishedName; -import org.springframework.dao.DataAccessException; -import javax.naming.directory.DirContext; -import java.util.List; -import java.util.Iterator; +import org.springframework.ldap.core.DirContextAdapter; /** * @author Luke Taylor * @version $Id$ */ -public class LdapUserDetailsManagerTests extends AbstractLdapServerTestCase { +public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests { private static final GrantedAuthority[] TEST_AUTHORITIES = new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_CLOWNS"), new GrantedAuthorityImpl("ROLE_ACROBATS")}; private LdapUserDetailsManager mgr; - private LdapTemplate template; + private SpringSecurityLdapTemplate template; - protected void onSetUp() { - mgr = new LdapUserDetailsManager(getInitialCtxFactory()); - template = new LdapTemplate(getInitialCtxFactory()); + protected void onSetUp() throws Exception { + super.onSetUp(); + mgr = new LdapUserDetailsManager(getContextSource()); + template = new SpringSecurityLdapTemplate(getContextSource()); DirContextAdapter ctx = new DirContextAdapter(); ctx.setAttributeValue("objectclass", "organizationalUnit"); @@ -57,10 +53,11 @@ public class LdapUserDetailsManagerTests extends AbstractLdapServerTestCase { group.setAttributeValue("objectclass", "groupOfNames"); group.setAttributeValue("cn", "clowns"); - template.bind("cn=clowns,ou=testgroups", ctx, null); + group.setAttributeValue("member", "cn=nobody,ou=testpeople,dc=acegisecurity,dc=org"); + template.bind("cn=clowns,ou=testgroups", group, null); group.setAttributeValue("cn", "acrobats"); - template.bind("cn=acrobats,ou=testgroups", ctx, null); + template.bind("cn=acrobats,ou=testgroups", group, null); mgr.setUserDnBase("ou=testpeople"); mgr.setGroupSearchBase("ou=testgroups"); @@ -70,21 +67,20 @@ public class LdapUserDetailsManagerTests extends AbstractLdapServerTestCase { } - protected void tearDown() throws Exception { - Iterator people = template.list("ou=testpeople").iterator(); + protected void onTearDown() throws Exception { +// Iterator people = template.list("ou=testpeople").iterator(); - DirContext rootCtx = new DirContextAdapter(new DistinguishedName(getInitialCtxFactory().getRootDn())); +// DirContext rootCtx = new DirContextAdapter(new DistinguishedName(getInitialCtxFactory().getRootDn())); +// +// while(people.hasNext()) { +// template.unbind((String) people.next() + ",ou=testpeople"); +// } - while(people.hasNext()) { - template.unbind(LdapUtils.getRelativeName((String) people.next(), rootCtx)); - } - - template.unbind("ou=testpeople"); - template.unbind("cn=acrobats,ou=testgroups"); - template.unbind("cn=clowns,ou=testgroups"); - template.unbind("ou=testgroups"); + template.unbind("ou=testpeople",true); + template.unbind("ou=testgroups",true); SecurityContextHolder.clearContext(); + super.onTearDown(); } public void testLoadUserByUsernameReturnsCorrectData() { @@ -154,26 +150,43 @@ public class LdapUserDetailsManagerTests extends AbstractLdapServerTestCase { assertEquals(0, mgr.getUserAuthorities(mgr.buildDn("don"), "don").length); } - public void testPasswordChangeSucceeds() { + public void testPasswordChangeWithCorrectOldPasswordSucceeds() { InetOrgPerson.Essence p = new InetOrgPerson.Essence(); p.setCn(new String[] {"John Yossarian"}); p.setSn("Yossarian"); - p.setUid("john"); + p.setUid("johnyossarian"); p.setPassword("yossarianspassword"); p.setAuthorities(TEST_AUTHORITIES); mgr.createUser(p.createUserDetails()); SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("john", "yossarianspassword", TEST_AUTHORITIES)); + new UsernamePasswordAuthenticationToken("johnyossarian", "yossarianspassword", TEST_AUTHORITIES)); mgr.changePassword("yossarianspassword", "yossariansnewpassword"); - + assertTrue(template.compare("uid=johnyossarian,ou=testpeople,dc=acegisecurity,dc=org", + "userPassword", "yossariansnewpassword")); + } + public void testPasswordChangeWithWrongOldPasswordFails() { + InetOrgPerson.Essence p = new InetOrgPerson.Essence(); + p.setCn(new String[] {"John Yossarian"}); + p.setSn("Yossarian"); + p.setUid("johnyossarian"); + p.setPassword("yossarianspassword"); + p.setAuthorities(TEST_AUTHORITIES); + mgr.createUser(p.createUserDetails()); + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken("johnyossarian", "yossarianspassword", TEST_AUTHORITIES)); + try { + mgr.changePassword("wrongpassword", "yossariansnewpassword"); + fail("Expected BadCredentialsException"); + } catch (BadCredentialsException expected) { + } } } diff --git a/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTests.java b/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTests.java index ee708328aa..aee18cfab7 100644 --- a/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTests.java +++ b/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTests.java @@ -20,9 +20,8 @@ import junit.framework.TestCase; import javax.naming.directory.BasicAttributes; import javax.naming.directory.BasicAttribute; -import org.acegisecurity.GrantedAuthorityImpl; -import org.springframework.ldap.support.DirContextAdapter; -import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DistinguishedName; /** * Tests {@link LdapUserDetailsMapper}.