SEC-1036: Upgraded Spring LDAP to 1.3 and made corresponding code changes. Also some general tidying up of LDAP code. Removed deprecated context factory classes.
This commit is contained in:
@@ -14,24 +14,25 @@
|
||||
*/
|
||||
package org.springframework.security.ldap;
|
||||
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.After;
|
||||
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
|
||||
import org.apache.directory.server.core.DirectoryService;
|
||||
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.Binding;
|
||||
import javax.naming.ContextNotEmptyException;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.apache.directory.server.core.DirectoryService;
|
||||
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Based on class borrowed from Spring Ldap project.
|
||||
@@ -40,7 +41,7 @@ import javax.naming.NameNotFoundException;
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AbstractLdapIntegrationTests {
|
||||
private static ClassPathXmlApplicationContext appContext;
|
||||
private static InMemoryXmlApplicationContext appContext;
|
||||
|
||||
protected AbstractLdapIntegrationTests() {
|
||||
}
|
||||
@@ -48,7 +49,7 @@ public abstract class AbstractLdapIntegrationTests {
|
||||
@BeforeClass
|
||||
public static void loadContext() throws NamingException {
|
||||
shutdownRunningServers();
|
||||
appContext = new ClassPathXmlApplicationContext("/org/springframework/security/ldap/ldapIntegrationTestContext.xml");
|
||||
appContext = new InMemoryXmlApplicationContext("<ldap-server port='53389' ldif='classpath:test-server.ldif'/>");
|
||||
|
||||
}
|
||||
|
||||
@@ -98,22 +99,14 @@ public abstract class AbstractLdapIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
public SpringSecurityContextSource getContextSource() {
|
||||
return (SpringSecurityContextSource) appContext.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
public BaseLdapPathContextSource getContextSource() {
|
||||
return (BaseLdapPathContextSource)appContext.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* We have both a context source and intitialdircontextfactory. The former is also used in
|
||||
* the cleanAndSetup method so any mods during tests can mess it up.
|
||||
* TODO: Once the initialdircontextfactory stuff has been refactored, revisit this and remove this property.
|
||||
*/
|
||||
protected DefaultInitialDirContextFactory getInitialDirContextFactory() {
|
||||
return (DefaultInitialDirContextFactory) appContext.getBean("initialDirContextFactory");
|
||||
}
|
||||
|
||||
private void clearSubContexts(DirContext ctx, Name name) throws NamingException {
|
||||
|
||||
NamingEnumeration enumeration = null;
|
||||
NamingEnumeration<Binding> enumeration = null;
|
||||
try {
|
||||
enumeration = ctx.listBindings(name);
|
||||
while (enumeration.hasMore()) {
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ldap;
|
||||
|
||||
import org.springframework.security.SpringSecurityMessageSource;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.ldap.UncategorizedLdapException;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.ldap.DefaultInitialDirContextFactory}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DefaultInitialDirContextFactoryTests extends AbstractLdapIntegrationTests {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
DefaultInitialDirContextFactory idf;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void onSetUp() throws Exception {
|
||||
super.onSetUp();
|
||||
idf = getInitialDirContextFactory();
|
||||
idf.setMessageSource(new SpringSecurityMessageSource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousBindSucceeds() throws Exception {
|
||||
DirContext ctx = idf.newInitialDirContext();
|
||||
// Connection pooling should be set by default for anon users.
|
||||
// Can't rely on this property being there with embedded server
|
||||
// assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseDnIsParsedFromCorrectlyFromUrl() {
|
||||
idf = new DefaultInitialDirContextFactory("ldap://springsecurity.org/dc=springframework,dc=org");
|
||||
assertEquals("dc=springframework,dc=org", idf.getRootDn());
|
||||
|
||||
// Check with an empty root
|
||||
idf = new DefaultInitialDirContextFactory("ldap://springsecurity.org/");
|
||||
assertEquals("", idf.getRootDn());
|
||||
|
||||
// Empty root without trailing slash
|
||||
idf = new DefaultInitialDirContextFactory("ldap://springsecurity.org");
|
||||
assertEquals("", idf.getRootDn());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindAsManagerFailsIfNoPasswordSet() throws Exception {
|
||||
idf.setManagerDn("uid=bob,ou=people,dc=springframework,dc=org");
|
||||
|
||||
DirContext ctx = null;
|
||||
|
||||
try {
|
||||
ctx = idf.newInitialDirContext();
|
||||
fail("Binding with no manager password should fail.");
|
||||
|
||||
// Can't rely on this property being there with embedded server
|
||||
// assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
||||
} catch (BadCredentialsException expected) {}
|
||||
|
||||
LdapUtils.closeContext(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindAsManagerSucceeds() throws Exception {
|
||||
idf.setManagerPassword("bobspassword");
|
||||
idf.setManagerDn("uid=bob,ou=people,dc=springframework,dc=org");
|
||||
|
||||
DirContext ctx = idf.newInitialDirContext();
|
||||
// Can't rely on this property being there with embedded server
|
||||
// assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionAsSpecificUserSucceeds() throws Exception {
|
||||
DirContext ctx = idf.newInitialDirContext("uid=Bob,ou=people,dc=springframework,dc=org", "bobspassword");
|
||||
// We don't want pooling for specific users.
|
||||
// assertNull(ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
||||
// com.sun.jndi.ldap.LdapPoolManager.showStats(System.out);
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionFailure() throws Exception {
|
||||
// Use the wrong port
|
||||
idf = new DefaultInitialDirContextFactory("ldap://localhost:60389");
|
||||
idf.setInitialContextFactory("com.sun.jndi.ldap.LdapCtxFactory");
|
||||
|
||||
Hashtable env = new Hashtable();
|
||||
env.put("com.sun.jndi.ldap.connect.timeout", "200");
|
||||
idf.setExtraEnvVars(env);
|
||||
idf.setUseConnectionPool(false); // coverage purposes only
|
||||
|
||||
try {
|
||||
idf.newInitialDirContext();
|
||||
fail("Connection succeeded unexpectedly");
|
||||
} catch (UncategorizedLdapException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnvironment() {
|
||||
idf = new DefaultInitialDirContextFactory("ldap://springsecurity.org/");
|
||||
|
||||
// check basic env
|
||||
Hashtable env = idf.getEnvironment();
|
||||
//assertEquals("com.sun.jndi.ldap.LdapCtxFactory", env.get(Context.INITIAL_CONTEXT_FACTORY));
|
||||
assertEquals("ldap://springsecurity.org/", env.get(Context.PROVIDER_URL));
|
||||
assertEquals("simple", env.get(Context.SECURITY_AUTHENTICATION));
|
||||
assertNull(env.get(Context.SECURITY_PRINCIPAL));
|
||||
assertNull(env.get(Context.SECURITY_CREDENTIALS));
|
||||
|
||||
// Ctx factory.
|
||||
idf.setInitialContextFactory("org.springframework.security.NonExistentCtxFactory");
|
||||
env = idf.getEnvironment();
|
||||
assertEquals("org.springframework.security.NonExistentCtxFactory", env.get(Context.INITIAL_CONTEXT_FACTORY));
|
||||
|
||||
// Auth type
|
||||
idf.setAuthenticationType("myauthtype");
|
||||
env = idf.getEnvironment();
|
||||
assertEquals("myauthtype", env.get(Context.SECURITY_AUTHENTICATION));
|
||||
|
||||
// Check extra vars
|
||||
Hashtable extraVars = new Hashtable();
|
||||
extraVars.put("extravar", "extravarvalue");
|
||||
idf.setExtraEnvVars(extraVars);
|
||||
env = idf.getEnvironment();
|
||||
assertEquals("extravarvalue", env.get("extravar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPasswordCausesBadCredentialsException() throws Exception {
|
||||
idf.setManagerDn("uid=bob,ou=people,dc=springframework,dc=org");
|
||||
idf.setManagerPassword("wrongpassword");
|
||||
|
||||
DirContext ctx = null;
|
||||
|
||||
try {
|
||||
ctx = idf.newInitialDirContext();
|
||||
fail("Binding with wrong credentials should fail.");
|
||||
} catch (BadCredentialsException expected) {}
|
||||
|
||||
LdapUtils.closeContext(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleProviderUrlsAreAccepted() {
|
||||
idf = new DefaultInitialDirContextFactory("ldaps://security.org/dc=springframework,dc=org "
|
||||
+ "ldap://monkeymachine.co.uk/dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleProviderUrlsWithDifferentRootsAreRejected() {
|
||||
try {
|
||||
idf = new DefaultInitialDirContextFactory("ldap://security.org/dc=springframework,dc=org "
|
||||
+ "ldap://monkeymachine.co.uk/dc=someotherplace,dc=org");
|
||||
fail("Different root DNs should cause an exception");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecureLdapUrlIsSupported() {
|
||||
idf = new DefaultInitialDirContextFactory("ldaps://localhost/dc=springframework,dc=org");
|
||||
assertEquals("dc=springframework,dc=org", idf.getRootDn());
|
||||
}
|
||||
|
||||
// public void testNonLdapUrlIsRejected() throws Exception {
|
||||
// DefaultInitialDirContextFactory idf = new DefaultInitialDirContextFactory();
|
||||
//
|
||||
// idf.setUrl("http://security.org/dc=springframework,dc=org");
|
||||
// idf.setInitialContextFactory(CoreContextFactory.class.getName());
|
||||
//
|
||||
// try {
|
||||
// idf.afterPropertiesSet();
|
||||
// fail("Expected exception for non 'ldap://' URL");
|
||||
// } catch(IllegalArgumentException expected) {
|
||||
// }
|
||||
// }
|
||||
@Test
|
||||
public void testServiceLocationUrlIsSupported() {
|
||||
idf = new DefaultInitialDirContextFactory("ldap:///dc=springframework,dc=org");
|
||||
assertEquals("dc=springframework,dc=org", idf.getRootDn());
|
||||
}
|
||||
}
|
||||
@@ -15,18 +15,20 @@
|
||||
|
||||
package org.springframework.security.ldap;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.ldap.NamingException;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockSpringSecurityContextSource implements SpringSecurityContextSource {
|
||||
public class MockSpringSecurityContextSource implements BaseLdapPathContextSource {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private DirContext ctx;
|
||||
@@ -52,7 +54,7 @@ public class MockSpringSecurityContextSource implements SpringSecurityContextSou
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public DirContext getReadWriteContext(String userDn, Object credentials) {
|
||||
public DirContext getContext(String principal, String credentials) throws NamingException {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ public class SpringSecurityAuthenticationSourceTests {
|
||||
user.setDn(new DistinguishedName("uid=joe,ou=users"));
|
||||
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken(user.createUserDetails(), null));
|
||||
new TestingAuthenticationToken(user.createUserDetails(), null));
|
||||
|
||||
assertEquals("uid=joe, ou=users", source.getPrincipal());
|
||||
assertEquals("uid=joe,ou=users", source.getPrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class PasswordComparisonAuthenticatorMockTests {
|
||||
final Attributes searchResults = new BasicAttributes("", null);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(dirCtx).search(with(equal("cn=Bob, ou=people")),
|
||||
oneOf(dirCtx).search(with(equal("cn=Bob,ou=people")),
|
||||
with(equal("(userPassword={0})")),
|
||||
with(aNonNull(Object[].class)),
|
||||
with(aNonNull(SearchControls.class)));
|
||||
|
||||
@@ -95,7 +95,7 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
|
||||
mgr.setGroupSearchBase("ou=groups");
|
||||
LdapUserDetails bob = (LdapUserDetails) mgr.loadUserByUsername("bob");
|
||||
assertEquals("bob", bob.getUsername());
|
||||
assertEquals("uid=bob, ou=people, dc=springframework, dc=org", bob.getDn());
|
||||
assertEquals("uid=bob,ou=people,dc=springframework,dc=org", bob.getDn());
|
||||
assertEquals("bobspassword", bob.getPassword());
|
||||
|
||||
assertEquals(1, bob.getAuthorities().size());
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<security:ldap-server port="53389" ldif="classpath:test-server.ldif"/>
|
||||
|
||||
<!--<import resource="classpath:/org/springframework/security/ldap/apacheDsContext.xml"/>-->
|
||||
|
||||
<bean id="initialDirContextFactory" class="org.springframework.security.ldap.DefaultInitialDirContextFactory" >
|
||||
<constructor-arg value="ldap://127.0.0.1:53389/dc=springframework,dc=org"/>
|
||||
<property name="useLdapContext" value="true"/>
|
||||
<property name="dirObjectFactory" value="org.springframework.ldap.core.support.DefaultDirObjectFactory" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user