1
0
mirror of synced 2026-08-03 08:51:58 +00:00

SEC-607: Deprecated InitialDirContextFactory and replaced it with SpringSecurityContextSource.

Also some refactoring of LdapUserDetailsManager to use a strategy for creating DNs from usernames.
This commit is contained in:
Luke Taylor
2007-11-20 20:54:48 +00:00
parent 79adaa2d3d
commit 9e2f372bad
31 changed files with 527 additions and 389 deletions
@@ -1,12 +1,12 @@
package org.springframework.security.config;
import org.springframework.security.ldap.InitialDirContextFactory;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
@@ -32,14 +32,13 @@ public class LdapBeanDefinitionParserTests {
@Test
public void testContextContainsExpectedBeansAndData() {
InitialDirContextFactory idcf = (InitialDirContextFactory) appContext.getBean("contextSource");
BaseLdapPathContextSource idcf = (BaseLdapPathContextSource) appContext.getBean("contextSource");
assertEquals("dc=springframework,dc=org", idcf.getRootDn());
// assertEquals("dc=springframework, dc=org", idcf.getBaseLdapPathAsString());
// Check data is loaded
LdapTemplate template = new LdapTemplate(idcf);
template.lookup("uid=ben,ou=people");
}
}
@@ -107,11 +107,11 @@ public abstract class AbstractLdapIntegrationTests {
loader.execute();
} finally {
ctx.close();
}
}
}
public ContextSource getContextSource() {
return (ContextSource) appContext.getBean("contextSource");
public SpringSecurityContextSource getContextSource() {
return (SpringSecurityContextSource) appContext.getBean("contextSource");
}
/**
@@ -0,0 +1,15 @@
package org.springframework.security.ldap;
import org.junit.Test;
/**
* @author Luke Taylor
* @version $Id$
*/
public class DefaultSpringSecurityContextSourceTests {
@Test
public void instantiationSucceeds() {
new DefaultSpringSecurityContextSource("ldap://blah:789/dc=springframework,dc=org");
}
}
@@ -71,6 +71,7 @@ public class LdapUtilsTests extends MockObjectTestCase {
public void testRootDnsAreParsedFromUrlsCorrectly() {
assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine"));
assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine:11389"));
assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/"));
assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/"));
assertEquals("dc=springframework,dc=org",
@@ -80,5 +81,7 @@ public class LdapUtilsTests extends MockObjectTestCase {
LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/dc=springframework,dc=org"));
assertEquals("dc=springframework,dc=org/ou=blah",
LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/dc=springframework,dc=org/ou=blah"));
assertEquals("dc=springframework,dc=org/ou=blah",
LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk:389/dc=springframework,dc=org/ou=blah"));
}
}
@@ -16,6 +16,7 @@
package org.springframework.security.ldap;
import org.springframework.dao.DataAccessException;
import org.springframework.ldap.core.DistinguishedName;
import javax.naming.directory.DirContext;
@@ -25,7 +26,7 @@ import javax.naming.directory.DirContext;
* @author Luke Taylor
* @version $Id$
*/
public class MockInitialDirContextFactory implements InitialDirContextFactory {
public class MockSpringSecurityContextSource implements SpringSecurityContextSource {
//~ Instance fields ================================================================================================
private DirContext ctx;
@@ -33,25 +34,13 @@ public class MockInitialDirContextFactory implements InitialDirContextFactory {
//~ Constructors ===================================================================================================
public MockInitialDirContextFactory(DirContext ctx, String baseDn) {
public MockSpringSecurityContextSource(DirContext ctx, String baseDn) {
this.baseDn = baseDn;
this.ctx = ctx;
}
//~ Methods ========================================================================================================
public String getRootDn() {
return baseDn;
}
public DirContext newInitialDirContext() {
return ctx;
}
public DirContext newInitialDirContext(String username, String password) {
return ctx;
}
public DirContext getReadOnlyContext() throws DataAccessException {
return ctx;
}
@@ -59,4 +48,16 @@ public class MockInitialDirContextFactory implements InitialDirContextFactory {
public DirContext getReadWriteContext() throws DataAccessException {
return ctx;
}
public DirContext getReadWriteContext(String userDn, Object credentials) {
return ctx;
}
public DistinguishedName getBaseLdapPath() {
return new DistinguishedName(baseDn);
}
public String getBaseLdapPathAsString() {
return getBaseLdapPath().toString();
}
}
@@ -44,33 +44,33 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
@Test
public void testCompareOfCorrectValueSucceeds() {
assertTrue(template.compare("uid=bob,ou=people,dc=springframework,dc=org", "uid", "bob"));
assertTrue(template.compare("uid=bob,ou=people", "uid", "bob"));
}
@Test
public void testCompareOfCorrectByteValueSucceeds() {
assertTrue(template.compare("uid=bob,ou=people,dc=springframework,dc=org", "userPassword", LdapUtils.getUtf8Bytes("bobspassword")));
assertTrue(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("bobspassword")));
}
@Test
public void testCompareOfWrongByteValueFails() {
assertFalse(template.compare("uid=bob,ou=people,dc=springframework,dc=org", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue")));
assertFalse(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue")));
}
@Test
public void testCompareOfWrongValueFails() {
assertFalse(template.compare("uid=bob,ou=people,dc=springframework,dc=org", "uid", "wrongvalue"));
assertFalse(template.compare("uid=bob,ou=people", "uid", "wrongvalue"));
}
@Test
public void testNameExistsForInValidNameFails() {
assertFalse(template.nameExists("ou=doesntexist,dc=springframework,dc=org"));
}
@Test
public void testNameExistsForValidNameSucceeds() {
assertTrue(template.nameExists("ou=groups,dc=springframework,dc=org"));
}
// @Test
// public void testNameExistsForInValidNameFails() {
// assertFalse(template.nameExists("ou=doesntexist,dc=springframework,dc=org"));
// }
//
// @Test
// public void testNameExistsForValidNameSucceeds() {
// assertTrue(template.nameExists("ou=groups,dc=springframework,dc=org"));
// }
@Test
public void testNamingExceptionIsTranslatedCorrectly() {
@@ -15,16 +15,15 @@
package org.springframework.security.ldap.search;
import org.springframework.security.ldap.DefaultInitialDirContextFactory;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.ldap.core.DirContextOperations;
import org.junit.Test;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Tests for FilterBasedLdapUserSearch.
@@ -35,13 +34,13 @@ import static org.junit.Assert.*;
public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests {
//~ Instance fields ================================================================================================
private DefaultInitialDirContextFactory dirCtxFactory;
private BaseLdapPathContextSource dirCtxFactory;
//~ Methods ========================================================================================================
public void onSetUp() throws Exception {
super.onSetUp();
dirCtxFactory = (DefaultInitialDirContextFactory) getContextSource();
dirCtxFactory = getContextSource();
}
@Test
@@ -54,8 +53,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
DirContextOperations bob = locator.searchForUser("bob");
assertEquals("bob", bob.getStringAttribute("uid"));
// name is wrong with embedded apacheDS
// assertEquals("uid=bob,ou=people,dc=springframework,dc=org", bob.getDn());
assertEquals(new DistinguishedName("uid=bob,ou=people"), bob.getDn());
}
// Try some funny business with filters.
@@ -71,24 +69,16 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
// assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn());
}
@Test
@Test(expected=IncorrectResultSizeDataAccessException.class)
public void testFailsOnMultipleMatches() {
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(cn=*)", dirCtxFactory);
try {
locator.searchForUser("Ignored");
fail("Expected exception for multiple search matches.");
} catch (IncorrectResultSizeDataAccessException expected) {}
locator.searchForUser("Ignored");
}
@Test
@Test(expected=UsernameNotFoundException.class)
public void testSearchForInvalidUserFails() {
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", dirCtxFactory);
try {
locator.searchForUser("Joe");
fail("Expected UsernameNotFoundException for non-existent user.");
} catch (UsernameNotFoundException expected) {}
locator.searchForUser("Joe");
}
@Test
@@ -100,7 +90,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
DirContextOperations ben = locator.searchForUser("Ben Alex");
assertEquals("ben", ben.getStringAttribute("uid"));
// assertEquals("uid=ben,ou=people,dc=springframework,dc=org", ben.getDn());
assertEquals(new DistinguishedName("uid=ben,ou=people"), ben.getDn());
}
// TODO: Add test with non-uid username
@@ -15,19 +15,17 @@
package org.springframework.security.providers.ldap.authenticator;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.Authentication;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.ldap.InitialDirContextFactory;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
/**
@@ -41,16 +39,16 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
private BindAuthenticator authenticator;
private Authentication bob;
private Authentication ben;
// private Authentication ben;
//~ Methods ========================================================================================================
public void onSetUp() {
authenticator = new BindAuthenticator((InitialDirContextFactory) getContextSource());
authenticator = new BindAuthenticator(getContextSource());
authenticator.setMessageSource(new SpringSecurityMessageSource());
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
// ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
}
@@ -74,7 +72,7 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
@Test
public void testAuthenticationWithUserSearch() throws Exception {
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people,dc=springframework,dc=org"));
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people"));
authenticator.setUserSearch(new MockUserSearch(ctx));
authenticator.afterPropertiesSet();
@@ -94,6 +92,6 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
@Test
public void testUserDnPatternReturnsCorrectDn() {
authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"});
assertEquals("cn=Joe,ou=people," + ((InitialDirContextFactory)getContextSource()).getRootDn(), authenticator.getUserDns("Joe").get(0));
assertEquals("cn=Joe,ou=people", authenticator.getUserDns("Joe").get(0));
}
}
@@ -15,7 +15,7 @@
package org.springframework.security.providers.ldap.authenticator;
import org.springframework.security.ldap.MockInitialDirContextFactory;
import org.springframework.security.ldap.MockSpringSecurityContextSource;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.jmock.Mock;
@@ -40,15 +40,15 @@ public class PasswordComparisonAuthenticatorMockTests extends MockObjectTestCase
BasicAttributes attrs = new BasicAttributes();
attrs.put(new BasicAttribute("uid", "bob"));
PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator(new MockInitialDirContextFactory(
(DirContext) mockCtx.proxy(), "dc=springframework,dc=org"));
PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator(new MockSpringSecurityContextSource(
(DirContext) mockCtx.proxy(), ""));
authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"});
// Get the mock to return an empty attribute set
mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=springframework,dc=org"));
mockCtx.expects(once()).method("lookup").with(eq("cn=Bob, ou=people")).will(returnValue(true));
mockCtx.expects(once()).method("getAttributes").with(eq("cn=Bob, ou=people"), NULL)
// mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=springframework,dc=org"));
// mockCtx.expects(once()).method("lookup").with(eq("cn=Bob,ou=people")).will(returnValue(true));
mockCtx.expects(once()).method("getAttributes").with(eq("cn=Bob,ou=people"), NULL)
.will(returnValue(attrs));
// Setup a single return value (i.e. success)
@@ -19,7 +19,6 @@ import org.springframework.security.BadCredentialsException;
import org.springframework.security.Authentication;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.ldap.InitialDirContextFactory;
import org.springframework.security.providers.encoding.PlaintextPasswordEncoder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
@@ -49,7 +48,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
public void onSetUp() throws Exception {
super.onSetUp();
authenticator = new PasswordComparisonAuthenticator((InitialDirContextFactory) getContextSource());
authenticator = new PasswordComparisonAuthenticator(getContextSource());
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
@@ -64,7 +63,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
@Test
public void testFailedSearchGivesUserNotFoundException() throws Exception {
authenticator = new PasswordComparisonAuthenticator((InitialDirContextFactory) getContextSource());
authenticator = new PasswordComparisonAuthenticator(getContextSource());
assertTrue("User DN matches shouldn't be available", authenticator.getUserDns("Bob").isEmpty());
authenticator.setUserSearch(new MockUserSearch(null));
authenticator.afterPropertiesSet();
@@ -164,7 +163,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
@Test
public void testWithUserSearch() {
authenticator = new PasswordComparisonAuthenticator((InitialDirContextFactory) getContextSource());
authenticator = new PasswordComparisonAuthenticator(getContextSource());
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"));
@@ -18,7 +18,6 @@ package org.springframework.security.providers.ldap.populator;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.ldap.InitialDirContextFactory;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
@@ -42,7 +41,7 @@ public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapIntegratio
public void onSetUp() throws Exception {
super.onSetUp();
populator = new DefaultLdapAuthoritiesPopulator((InitialDirContextFactory) getContextSource(), "ou=groups");
populator = new DefaultLdapAuthoritiesPopulator(getContextSource(), "ou=groups");
}
@@ -14,20 +14,20 @@
*/
package org.springframework.security.userdetails.ldap;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.ldap.core.DirContextAdapter;
import static org.junit.Assert.*;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Test;
/**
@@ -63,7 +63,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
group.setAttributeValue("cn", "acrobats");
template.bind("cn=acrobats,ou=testgroups", group, null);
mgr.setUserDnBase("ou=testpeople");
mgr.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=testpeople","uid"));
mgr.setGroupSearchBase("ou=testgroups");
mgr.setGroupRoleAttributeName("cn");
mgr.setGroupMemberAttributeName("member");
@@ -88,7 +88,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
@Test
public void testLoadUserByUsernameReturnsCorrectData() {
mgr.setUserDnBase("ou=people");
mgr.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=people","uid"));
mgr.setGroupSearchBase("ou=groups");
UserDetails bob = mgr.loadUserByUsername("bob");
assertEquals("bob", bob.getUsername());
@@ -111,7 +111,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
@Test
public void testUserExistsReturnsTrueForValidUser() {
mgr.setUserDnBase("ou=people");
mgr.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=people","uid"));
assertTrue(mgr.userExists("bob"));
}
@@ -156,7 +156,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
}
// Check that no authorities are left
assertEquals(0, mgr.getUserAuthorities(mgr.buildDn("don"), "don").length);
assertEquals(0, mgr.getUserAuthorities(mgr.usernameMapper.buildDn("don"), "don").length);
}
@Test
@@ -175,7 +175,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
mgr.changePassword("yossarianspassword", "yossariansnewpassword");
assertTrue(template.compare("uid=johnyossarian,ou=testpeople,dc=springframework,dc=org",
assertTrue(template.compare("uid=johnyossarian,ou=testpeople",
"userPassword", "yossariansnewpassword"));
}