Added support for multiple DN patterns. Changes to favour constructor injection for mandatory properties. Renamed LdapUserInfo to prevent confusion with UserDetails interface.
This commit is contained in:
parent
e3b728cc9a
commit
1f66750e24
|
@ -25,7 +25,6 @@ import javax.naming.directory.InitialDirContext;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -39,7 +38,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
* This should be in the form <tt>ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org</tt>.
|
* This should be in the form <tt>ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org</tt>.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* To obtain an initial context, th client calls the <tt>newInitialDirContext</tt>
|
* To obtain an initial context, the client calls the <tt>newInitialDirContext</tt>
|
||||||
* method. There are two signatures - one with no arguments and one which allows
|
* method. There are two signatures - one with no arguments and one which allows
|
||||||
* binding with a specific username and password.
|
* binding with a specific username and password.
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -53,16 +52,15 @@ import org.apache.commons.logging.LogFactory;
|
||||||
* as a specific user.
|
* as a specific user.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see <a href="http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html">The Java tutorial's guide to
|
* @see <a href="http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html">The Java
|
||||||
* Connection Pooling</a>
|
* tutorial's guide to LDAP connection pooling</a>
|
||||||
*
|
*
|
||||||
* @author Robert Sanders
|
* @author Robert Sanders
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DefaultInitialDirContextFactory implements InitialDirContextFactory,
|
public class DefaultInitialDirContextFactory implements InitialDirContextFactory {
|
||||||
InitializingBean {
|
|
||||||
|
|
||||||
//~ Static fields/initializers =============================================
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
|
@ -118,13 +116,39 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
*/
|
*/
|
||||||
private boolean useConnectionPool = true;
|
private boolean useConnectionPool = true;
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public DefaultInitialDirContextFactory(String url) {
|
||||||
|
this.url = url;
|
||||||
|
|
||||||
|
Assert.hasLength(url, "An LDAP connection URL must be supplied.");
|
||||||
|
|
||||||
|
if(url.startsWith("ldap:")) {
|
||||||
|
|
||||||
|
URI uri = LdapUtils.parseLdapUrl(url);
|
||||||
|
|
||||||
|
rootDn = uri.getPath();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Assume it's an embedded server
|
||||||
|
rootDn = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rootDn.startsWith("/")) {
|
||||||
|
rootDn = rootDn.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't necessarily hold for embedded servers.
|
||||||
|
//Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'");
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects anonymously unless a manager user has been specified, in which case
|
* Connects anonymously unless a manager user has been specified, in which case
|
||||||
* it will bind as the manager.
|
* it will bind as the manager.
|
||||||
*
|
*
|
||||||
* @return the resulting
|
* @return the resulting context object.
|
||||||
*/
|
*/
|
||||||
public DirContext newInitialDirContext() {
|
public DirContext newInitialDirContext() {
|
||||||
|
|
||||||
|
@ -152,7 +176,8 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The Hashtable describing the base DirContext that will be created, minus the username/password if any.
|
* @return the Hashtable describing the base DirContext that will be created,
|
||||||
|
* minus the username/password if any.
|
||||||
*/
|
*/
|
||||||
protected Hashtable getEnvironment() {
|
protected Hashtable getEnvironment() {
|
||||||
Hashtable env = new Hashtable();
|
Hashtable env = new Hashtable();
|
||||||
|
@ -174,8 +199,15 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
|
|
||||||
private InitialDirContext connect(Hashtable env) {
|
private InitialDirContext connect(Hashtable env) {
|
||||||
|
|
||||||
// Prints the password, so don't use except for debugging.
|
if(logger.isDebugEnabled()) {
|
||||||
// logger.debug("Creating initial context with env " + env);
|
Hashtable envClone = (Hashtable)env.clone();
|
||||||
|
|
||||||
|
if(envClone.containsKey(Context.SECURITY_CREDENTIALS)) {
|
||||||
|
envClone.put(Context.SECURITY_CREDENTIALS, "******");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Creating InitialDirContext with environment " + envClone);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new InitialDirContext(env);
|
return new InitialDirContext(env);
|
||||||
|
@ -189,27 +221,6 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
Assert.hasLength(url, "An LDAP connection URL must be supplied.");
|
|
||||||
|
|
||||||
if(url.startsWith("ldap:")) {
|
|
||||||
|
|
||||||
URI uri = new URI(url);
|
|
||||||
|
|
||||||
rootDn = uri.getPath();
|
|
||||||
} else {
|
|
||||||
// Assume it's an embedded server
|
|
||||||
rootDn = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rootDn.startsWith("/")) {
|
|
||||||
rootDn = rootDn.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the root DN of the configured provider URL. For example,
|
* Returns the root DN of the configured provider URL. For example,
|
||||||
* if the URL is <tt>ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org</tt>
|
* if the URL is <tt>ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org</tt>
|
||||||
|
@ -222,12 +233,12 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuthenticationType(String authenticationType) {
|
public void setAuthenticationType(String authenticationType) {
|
||||||
Assert.hasLength(authenticationType);
|
Assert.hasLength(authenticationType, "LDAP Authentication type must not be empty or null");
|
||||||
this.authenticationType = authenticationType;
|
this.authenticationType = authenticationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInitialContextFactory(String initialContextFactory) {
|
public void setInitialContextFactory(String initialContextFactory) {
|
||||||
Assert.hasLength(initialContextFactory);
|
Assert.hasLength(initialContextFactory, "Initial context factory name cannot be empty or null");
|
||||||
this.initialContextFactory = initialContextFactory;
|
this.initialContextFactory = initialContextFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +246,7 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
* @param managerDn The name of the "manager" user for default authentication.
|
* @param managerDn The name of the "manager" user for default authentication.
|
||||||
*/
|
*/
|
||||||
public void setManagerDn(String managerDn) {
|
public void setManagerDn(String managerDn) {
|
||||||
|
Assert.hasLength(managerDn, "Manager user name cannot be empty or null.");
|
||||||
this.managerDn = managerDn;
|
this.managerDn = managerDn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,18 +254,15 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||||
* @param managerPassword The "manager" user's password.
|
* @param managerPassword The "manager" user's password.
|
||||||
*/
|
*/
|
||||||
public void setManagerPassword(String managerPassword) {
|
public void setManagerPassword(String managerPassword) {
|
||||||
|
Assert.hasLength(managerPassword, "Manager password must not be empty or null.");
|
||||||
this.managerPassword = managerPassword;
|
this.managerPassword = managerPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUrl(String url) {
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param extraEnvVars extra environment variables to be added at config time.
|
* @param extraEnvVars extra environment variables to be added at config time.
|
||||||
*/
|
*/
|
||||||
public void setExtraEnvVars(Map extraEnvVars) {
|
public void setExtraEnvVars(Map extraEnvVars) {
|
||||||
|
Assert.notNull(extraEnvVars, "Extra environment map cannot be null.");
|
||||||
this.extraEnvVars = extraEnvVars;
|
this.extraEnvVars = extraEnvVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,24 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||||
|
|
||||||
private LdapAuthenticator authenticator;
|
private LdapAuthenticator authenticator;
|
||||||
|
|
||||||
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
|
private LdapAuthoritiesPopulator authoritiesPopulator;
|
||||||
|
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public LdapAuthenticationProvider(LdapAuthenticator authenticator,
|
||||||
|
LdapAuthoritiesPopulator authoritiesPopulator) {
|
||||||
|
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
|
||||||
|
Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied");
|
||||||
|
|
||||||
|
this.authenticator = authenticator;
|
||||||
|
this.authoritiesPopulator = authoritiesPopulator;
|
||||||
|
|
||||||
|
// TODO: Check that the role attributes specified for the populator will be retrieved
|
||||||
|
// by the authenticator. If not, add them to the authenticator's list and log a
|
||||||
|
// warning.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
@ -89,21 +106,11 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||||
String password = (String)authentication.getCredentials();
|
String password = (String)authentication.getCredentials();
|
||||||
Assert.notNull(password, "Null password was supplied in authentication token");
|
Assert.notNull(password, "Null password was supplied in authentication token");
|
||||||
|
|
||||||
LdapUserDetails ldapUser = authenticator.authenticate(username, password);
|
LdapUserInfo ldapUser = authenticator.authenticate(username, password);
|
||||||
|
|
||||||
return createUserDetails(username, password, ldapUser.getDn(), ldapUser.getAttributes());
|
return createUserDetails(username, password, ldapUser.getDn(), ldapUser.getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doAfterPropertiesSet() throws Exception {
|
|
||||||
super.doAfterPropertiesSet();
|
|
||||||
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
|
|
||||||
Assert.notNull(ldapAuthoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied");
|
|
||||||
|
|
||||||
// TODO: Check that the role attributes specified for the populator will be retrieved
|
|
||||||
// by the authenticator. If not, add them to the authenticator's list and log a
|
|
||||||
// warning.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the user final <tt>UserDetails</tt> object that will be returned by the provider
|
* Creates the user final <tt>UserDetails</tt> object that will be returned by the provider
|
||||||
* once the user has been authenticated.
|
* once the user has been authenticated.
|
||||||
|
@ -124,15 +131,8 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||||
protected UserDetails createUserDetails(String username, String password, String userDn, Attributes attributes) {
|
protected UserDetails createUserDetails(String username, String password, String userDn, Attributes attributes) {
|
||||||
|
|
||||||
return new User(username, password, true, true, true, true,
|
return new User(username, password, true, true, true, true,
|
||||||
ldapAuthoritiesPopulator.getGrantedAuthorities(username, userDn, attributes));
|
authoritiesPopulator.getGrantedAuthorities(username, userDn, attributes));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuthenticator(LdapAuthenticator authenticator) {
|
|
||||||
this.authenticator = authenticator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLdapAuthoritiesPopulator(LdapAuthoritiesPopulator ldapAuthoritiesPopulator) {
|
|
||||||
this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,5 +35,5 @@ public interface LdapAuthenticator {
|
||||||
* @param password the user's password supplied at login.
|
* @param password the user's password supplied at login.
|
||||||
* @return the details of the successfully authenticated user.
|
* @return the details of the successfully authenticated user.
|
||||||
*/
|
*/
|
||||||
LdapUserDetails authenticate(String username, String password);
|
LdapUserInfo authenticate(String username, String password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,15 @@ import javax.naming.directory.Attributes;
|
||||||
public interface LdapAuthoritiesPopulator {
|
public interface LdapAuthoritiesPopulator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get the list of authorities for the user.
|
||||||
*
|
*
|
||||||
* @param username the login name which was passed to the LDAP provider.
|
* @param username the login name which was passed to the LDAP provider.
|
||||||
* @param userDn the full DN of the user
|
* @param userDn the full DN of the user
|
||||||
* @param userAttributes the user's LDAP attributes that were retrieved from the directory.
|
* @param userAttributes the user's LDAP attributes that were retrieved from the directory.
|
||||||
* @return the granted authorities for the given user.
|
* @return the granted authorities for the given user.
|
||||||
|
* @throws LdapDataAccessException if there is a problem accessing the directory.
|
||||||
*/
|
*/
|
||||||
GrantedAuthority[] getGrantedAuthorities(String username, String userDn, Attributes userAttributes);
|
GrantedAuthority[] getGrantedAuthorities(String username, String userDn, Attributes userAttributes)
|
||||||
|
throws LdapDataAccessException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,6 @@
|
||||||
|
|
||||||
package org.acegisecurity.providers.ldap;
|
package org.acegisecurity.providers.ldap;
|
||||||
|
|
||||||
import org.acegisecurity.userdetails.User;
|
|
||||||
import org.acegisecurity.GrantedAuthority;
|
|
||||||
import org.acegisecurity.GrantedAuthorityImpl;
|
|
||||||
|
|
||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
|
@ -40,7 +36,7 @@ import javax.naming.NamingException;
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class LdapUserDetails {
|
public class LdapUserInfo {
|
||||||
|
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
@ -54,7 +50,7 @@ public class LdapUserDetails {
|
||||||
* @param dn the full DN of the user
|
* @param dn the full DN of the user
|
||||||
* @param attributes any attributes loaded from the user's directory entry.
|
* @param attributes any attributes loaded from the user's directory entry.
|
||||||
*/
|
*/
|
||||||
public LdapUserDetails(String dn, Attributes attributes) {
|
public LdapUserInfo(String dn, Attributes attributes) {
|
||||||
this.dn = dn;
|
this.dn = dn;
|
||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
}
|
}
|
|
@ -22,6 +22,8 @@ import org.springframework.util.Assert;
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDAP Utility methods.
|
* LDAP Utility methods.
|
||||||
|
@ -46,6 +48,22 @@ public class LdapUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the supplied LDAP URL.
|
||||||
|
* @param url the URL (e.g. <tt>ldap://monkeymachine:11389/dc=acegisecurity,dc=org</tt>).
|
||||||
|
* @return the URI object created from the URL
|
||||||
|
* @throws IllegalArgumentException if the URL is null, empty or the URI syntax is invalid.
|
||||||
|
*/
|
||||||
|
public static URI parseLdapUrl(String url) {
|
||||||
|
Assert.hasLength(url);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URI(url);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("Unable to parse url: " + url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] getUtf8Bytes(String s) {
|
public static byte[] getUtf8Bytes(String s) {
|
||||||
try {
|
try {
|
||||||
return s.getBytes("UTF-8");
|
return s.getBytes("UTF-8");
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
|
@ -31,36 +33,52 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator,
|
||||||
|
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
private String userDnPattern = null;
|
//private String[] userDnPattern = null;
|
||||||
private MessageFormat userDnFormat = null;
|
private MessageFormat[] userDnFormat = null;
|
||||||
private InitialDirContextFactory initialDirContextFactory;
|
private InitialDirContextFactory initialDirContextFactory;
|
||||||
private LdapUserSearch userSearch;
|
private LdapUserSearch userSearch;
|
||||||
private String[] userAttributes = null;
|
private String[] userAttributes = null;
|
||||||
|
private String dnSuffix = "";
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
protected AbstractLdapAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||||
|
Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null.");
|
||||||
|
this.initialDirContextFactory = initialDirContextFactory;
|
||||||
|
|
||||||
|
String rootDn = initialDirContextFactory.getRootDn();
|
||||||
|
|
||||||
|
if(rootDn.length() > 0) {
|
||||||
|
dnSuffix = "," + rootDn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the DN of the user, worked out from the userDNPattern property.
|
* Builds list of possible DNs for the user, worked out from the
|
||||||
* The returned value includes the root DN of the provider
|
* <tt>userDnPatterns</tt> property. The returned value includes the root DN of
|
||||||
* URL used to configure the <tt>InitialDirContextfactory</tt>.
|
* the provider URL used to configure the <tt>InitialDirContextfactory</tt>.
|
||||||
|
*
|
||||||
|
* @param username the user's login name
|
||||||
|
* @return the list of possible DN matches, empty if <tt>userDnPatterns</tt> wasn't
|
||||||
|
* set.
|
||||||
*/
|
*/
|
||||||
protected String getUserDn(String username) {
|
protected List getUserDns(String username) {
|
||||||
if(userDnFormat == null) {
|
if(userDnFormat == null) {
|
||||||
return null;
|
return new ArrayList(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
String rootDn = initialDirContextFactory.getRootDn();
|
List userDns = new ArrayList(userDnFormat.length);
|
||||||
String userDn;
|
String[] args = new String[] {username};
|
||||||
|
|
||||||
synchronized( userDnFormat ) {
|
synchronized( userDnFormat ) {
|
||||||
userDn = userDnFormat.format(new String[] {username});
|
for(int i=0; i < userDnFormat.length; i++) {
|
||||||
|
userDns.add( userDnFormat[i].format(args) + dnSuffix );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rootDn.length() > 0) {
|
return userDns;
|
||||||
userDn = userDn + "," + rootDn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return userDn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,50 +87,45 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator,
|
||||||
* The pattern argument {0} will contain the username.
|
* The pattern argument {0} will contain the username.
|
||||||
* An example would be "cn={0},ou=people".
|
* An example would be "cn={0},ou=people".
|
||||||
*/
|
*/
|
||||||
public void setUserDnPattern(String dnPattern) {
|
public void setUserDnPatterns(String[] dnPattern) {
|
||||||
this.userDnPattern = dnPattern;
|
Assert.notNull(dnPattern, "The array of DN patterns cannot be set to null");
|
||||||
userDnFormat = null;
|
// this.userDnPattern = dnPattern;
|
||||||
|
userDnFormat = new MessageFormat[dnPattern.length];
|
||||||
|
|
||||||
if(dnPattern != null) {
|
for(int i=0; i < dnPattern.length; i++) {
|
||||||
userDnFormat = new MessageFormat(dnPattern);
|
userDnFormat[i] = new MessageFormat(dnPattern[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getUserAttributes() {
|
|
||||||
return userAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserDnPattern() {
|
|
||||||
return userDnPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserSearch(LdapUserSearch userSearch) {
|
|
||||||
this.userSearch = userSearch;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected LdapUserSearch getUserSearch() {
|
|
||||||
return userSearch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
|
|
||||||
this.initialDirContextFactory = initialDirContextFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user attributes which will be retrieved from the directory.
|
* Sets the user attributes which will be retrieved from the directory.
|
||||||
*
|
*
|
||||||
* @param userAttributes
|
* @param userAttributes
|
||||||
*/
|
*/
|
||||||
public void setUserAttributes(String[] userAttributes) {
|
public void setUserAttributes(String[] userAttributes) {
|
||||||
|
Assert.notNull(userAttributes, "The userAttributes property cannot be set to null");
|
||||||
this.userAttributes = userAttributes;
|
this.userAttributes = userAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getUserAttributes() {
|
||||||
|
return userAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSearch(LdapUserSearch userSearch) {
|
||||||
|
Assert.notNull(userSearch, "The userSearch cannot be set to null");
|
||||||
|
this.userSearch = userSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LdapUserSearch getUserSearch() {
|
||||||
|
return userSearch;
|
||||||
|
}
|
||||||
|
|
||||||
protected InitialDirContextFactory getInitialDirContextFactory() {
|
protected InitialDirContextFactory getInitialDirContextFactory() {
|
||||||
return initialDirContextFactory;
|
return initialDirContextFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
Assert.notNull(initialDirContextFactory, "initialDirContextFactory must be supplied.");
|
Assert.isTrue(userDnFormat != null || userSearch != null,
|
||||||
Assert.isTrue(userDnPattern != null || userSearch != null, "Either an LdapUserSearch or DN pattern (or both) must be supplied.");
|
"Either an LdapUserSearch or DN pattern (or both) must be supplied.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An authenticator which binds as a user.
|
* An authenticator which binds as a user.
|
||||||
|
@ -32,28 +33,35 @@ import javax.naming.NamingException;
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class BindAuthenticator extends AbstractLdapAuthenticator {
|
public final class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||||
|
|
||||||
//~ Static fields/initializers =============================================
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(BindAuthenticator.class);
|
private static final Log logger = LogFactory.getLog(BindAuthenticator.class);
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public BindAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||||
|
super(initialDirContextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
public LdapUserDetails authenticate(String username, String password) {
|
public LdapUserInfo authenticate(String username, String password) {
|
||||||
|
|
||||||
String dn = getUserDn(username);
|
LdapUserInfo user = null;
|
||||||
LdapUserDetails user = null;
|
|
||||||
|
|
||||||
// If DN is pattern is configured, try authenticating with that directly
|
// If DN patterns are configured, try authenticating with them directly
|
||||||
if(dn != null) {
|
Iterator dns = getUserDns(username).iterator();
|
||||||
user = authenticateWithDn(dn, password);
|
|
||||||
|
while(dns.hasNext() && user == null) {
|
||||||
|
user = authenticateWithDn((String)dns.next(), password);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise use the configured locator to find the user
|
// Otherwise use the configured locator to find the user
|
||||||
// and authenticate with the returned DN.
|
// and authenticate with the returned DN.
|
||||||
if(user == null && getUserSearch() != null) {
|
if(user == null && getUserSearch() != null) {
|
||||||
LdapUserDetails userFromSearch = getUserSearch().searchForUser(username);
|
LdapUserInfo userFromSearch = getUserSearch().searchForUser(username);
|
||||||
user = authenticateWithDn(userFromSearch.getDn(), password);
|
user = authenticateWithDn(userFromSearch.getDn(), password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,13 +73,13 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LdapUserDetails authenticateWithDn(String userDn, String password) {
|
private LdapUserInfo authenticateWithDn(String userDn, String password) {
|
||||||
DirContext ctx = null;
|
DirContext ctx = null;
|
||||||
LdapUserDetails user = null;
|
LdapUserInfo user = null;
|
||||||
Attributes attributes = null;
|
Attributes attributes = null;
|
||||||
|
|
||||||
if(logger.isDebugEnabled()) {
|
if(logger.isDebugEnabled()) {
|
||||||
logger.debug("Binding with DN = " + userDn);
|
logger.debug("Attempting to bind with DN = " + userDn);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -79,7 +87,7 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||||
attributes = ctx.getAttributes(
|
attributes = ctx.getAttributes(
|
||||||
LdapUtils.getRelativeName(userDn, ctx),
|
LdapUtils.getRelativeName(userDn, ctx),
|
||||||
getUserAttributes());
|
getUserAttributes());
|
||||||
user = new LdapUserDetails(userDn, attributes);
|
user = new LdapUserInfo(userDn, attributes);
|
||||||
|
|
||||||
} catch(NamingException ne) {
|
} catch(NamingException ne) {
|
||||||
throw new LdapDataAccessException("Failed to load attributes for user " + userDn, ne);
|
throw new LdapDataAccessException("Failed to load attributes for user " + userDn, ne);
|
||||||
|
|
|
@ -84,12 +84,12 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch {
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the LdapUserDetails containing the user's information, or null if
|
* Return the LdapUserInfo containing the user's information, or null if
|
||||||
* no SearchResult is found.
|
* no SearchResult is found.
|
||||||
*
|
*
|
||||||
* @param username the username to search for.
|
* @param username the username to search for.
|
||||||
*/
|
*/
|
||||||
public LdapUserDetails searchForUser(String username) {
|
public LdapUserInfo searchForUser(String username) {
|
||||||
DirContext ctx = initialDirContextFactory.newInitialDirContext();
|
DirContext ctx = initialDirContextFactory.newInitialDirContext();
|
||||||
SearchControls ctls = new SearchControls();
|
SearchControls ctls = new SearchControls();
|
||||||
ctls.setTimeLimit( searchTimeLimit );
|
ctls.setTimeLimit( searchTimeLimit );
|
||||||
|
@ -120,7 +120,7 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch {
|
||||||
userDn.append(",");
|
userDn.append(",");
|
||||||
userDn.append(ctx.getNameInNamespace());
|
userDn.append(ctx.getNameInNamespace());
|
||||||
|
|
||||||
return new LdapUserDetails(userDn.toString(), searchResult.getAttributes());
|
return new LdapUserInfo(userDn.toString(), searchResult.getAttributes());
|
||||||
|
|
||||||
} catch(NamingException ne) {
|
} catch(NamingException ne) {
|
||||||
throw new LdapDataAccessException("User Couldn't be found due to exception", ne);
|
throw new LdapDataAccessException("User Couldn't be found due to exception", ne);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
package org.acegisecurity.providers.ldap.authenticator;
|
package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains a user's information from the LDAP directory given a login name.
|
* Obtains a user's information from the LDAP directory given a login name.
|
||||||
|
@ -35,9 +35,9 @@ public interface LdapUserSearch {
|
||||||
* for that user.
|
* for that user.
|
||||||
*
|
*
|
||||||
* @param username the login name supplied to the authentication service.
|
* @param username the login name supplied to the authentication service.
|
||||||
* @return an LdapUserDetails object containing the user's full DN and requested attributes.
|
* @return an LdapUserInfo object containing the user's full DN and requested attributes.
|
||||||
* TODO: Need to optionally supply required attributes here for the search.
|
* TODO: Need to optionally supply required attributes here for the search.
|
||||||
*/
|
*/
|
||||||
LdapUserDetails searchForUser(String username);
|
LdapUserInfo searchForUser(String username);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
|
|
||||||
package org.acegisecurity.providers.ldap.authenticator;
|
package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
import org.acegisecurity.providers.ldap.LdapUtils;
|
import org.acegisecurity.providers.ldap.LdapUtils;
|
||||||
|
import org.acegisecurity.providers.ldap.InitialDirContextFactory;
|
||||||
import org.acegisecurity.providers.encoding.PasswordEncoder;
|
import org.acegisecurity.providers.encoding.PasswordEncoder;
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||||
|
@ -29,6 +30,7 @@ import javax.naming.NamingException;
|
||||||
import javax.naming.directory.SearchControls;
|
import javax.naming.directory.SearchControls;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.directory.Attribute;
|
import javax.naming.directory.Attribute;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link org.acegisecurity.providers.ldap.LdapAuthenticator LdapAuthenticator}
|
* An {@link org.acegisecurity.providers.ldap.LdapAuthenticator LdapAuthenticator}
|
||||||
|
@ -49,7 +51,7 @@ import javax.naming.directory.Attribute;
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
|
public final class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
|
||||||
//~ Static fields/initializers =============================================
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class);
|
private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class);
|
||||||
|
@ -64,21 +66,28 @@ public class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
|
||||||
|
|
||||||
private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder();
|
private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder();
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public PasswordComparisonAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||||
|
super(initialDirContextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
public LdapUserDetails authenticate(String username, String password) {
|
public LdapUserInfo authenticate(String username, String password) {
|
||||||
|
|
||||||
// locate the user and check the password
|
// locate the user and check the password
|
||||||
String userDn = getUserDn(username);
|
LdapUserInfo user = null;
|
||||||
LdapUserDetails user = null;
|
|
||||||
|
|
||||||
DirContext ctx = getInitialDirContextFactory().newInitialDirContext();
|
DirContext ctx = getInitialDirContextFactory().newInitialDirContext();
|
||||||
|
Iterator dns = getUserDns(username).iterator();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(userDn != null) {
|
while(dns.hasNext() && user == null) {
|
||||||
|
String userDn = (String)dns.next();
|
||||||
String relativeName = LdapUtils.getRelativeName(userDn, ctx);
|
String relativeName = LdapUtils.getRelativeName(userDn, ctx);
|
||||||
|
|
||||||
user = new LdapUserDetails(userDn,
|
user = new LdapUserInfo(userDn,
|
||||||
ctx.getAttributes(relativeName, getUserAttributes()));
|
ctx.getAttributes(relativeName, getUserAttributes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +114,10 @@ public class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if(logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Password attribute " + passwordAttributeName
|
||||||
|
+ " wasn't retrieved for user " + username);
|
||||||
|
}
|
||||||
|
|
||||||
doPasswordCompare(ctx, user.getRelativeName(ctx), password);
|
doPasswordCompare(ctx, user.getRelativeName(ctx), password);
|
||||||
}
|
}
|
||||||
|
@ -153,7 +166,7 @@ public class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPasswordAttributeName(String passwordAttribute) {
|
public void setPasswordAttributeName(String passwordAttribute) {
|
||||||
Assert.hasLength(passwordAttribute, "passwordAttribute must not be empty or null");
|
Assert.hasLength(passwordAttribute, "passwordAttributeName must not be empty or null");
|
||||||
this.passwordAttributeName = passwordAttribute;
|
this.passwordAttributeName = passwordAttribute;
|
||||||
this.passwordCompareFilter = "(" + passwordAttributeName + "={0})";
|
this.passwordCompareFilter = "(" + passwordAttributeName + "={0})";
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.acegisecurity.GrantedAuthorityImpl;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
|
|
||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.Attribute;
|
import javax.naming.directory.Attribute;
|
||||||
|
@ -85,17 +84,18 @@ import java.util.HashSet;
|
||||||
* setting the <tt>groupRoleAttribute</tt> property (the default is "cn").
|
* setting the <tt>groupRoleAttribute</tt> property (the default is "cn").
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
|
* <pre>
|
||||||
* <bean id="ldapAuthoritiesPopulator" class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
* <bean id="ldapAuthoritiesPopulator" class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
||||||
* TODO
|
* TODO
|
||||||
* </bean>
|
* </bean>
|
||||||
|
* </pre>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator,
|
public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
|
||||||
InitializingBean {
|
|
||||||
//~ Static fields/initializers =============================================
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(DefaultLdapAuthoritiesPopulator.class);
|
private static final Log logger = LogFactory.getLog(DefaultLdapAuthoritiesPopulator.class);
|
||||||
|
@ -105,7 +105,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
/** Attributes of the User's LDAP Object that contain role name information. */
|
/** Attributes of the User's LDAP Object that contain role name information. */
|
||||||
private String[] userRoleAttributes = null;
|
private String[] userRoleAttributes = null;
|
||||||
|
|
||||||
private String rolePrefix = "";
|
private String rolePrefix = "ROLE_";
|
||||||
|
|
||||||
/** The base DN from which the search for group membership should be performed */
|
/** The base DN from which the search for group membership should be performed */
|
||||||
private String groupSearchBase = null;
|
private String groupSearchBase = null;
|
||||||
|
@ -127,6 +127,30 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
/** An initial context factory is only required if searching for groups is required. */
|
/** An initial context factory is only required if searching for groups is required. */
|
||||||
private InitialDirContextFactory initialDirContextFactory = null;
|
private InitialDirContextFactory initialDirContextFactory = null;
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for non-group search scenarios. Typically in this case
|
||||||
|
* the <tt>userRoleAttributes</tt> property will be set to obtain roles directly
|
||||||
|
* from the user's directory entry attributes.
|
||||||
|
*/
|
||||||
|
public DefaultLdapAuthoritiesPopulator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for group search scenarios. <tt>userRoleAttributes</tt> may still be
|
||||||
|
* set as a property.
|
||||||
|
*
|
||||||
|
* @param initialDirContextFactory
|
||||||
|
* @param groupSearchBase
|
||||||
|
*/
|
||||||
|
public DefaultLdapAuthoritiesPopulator(InitialDirContextFactory initialDirContextFactory, String groupSearchBase) {
|
||||||
|
Assert.notNull(initialDirContextFactory, "InitialDirContextFactory must not be null");
|
||||||
|
Assert.hasLength(groupSearchBase, "The groupSearchBase (name to search under), must be specified.");
|
||||||
|
this.initialDirContextFactory = initialDirContextFactory;
|
||||||
|
this.groupSearchBase = groupSearchBase;
|
||||||
|
}
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,6 +200,12 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Searching for roles for user '"
|
||||||
|
+ userDn + "', with filter "+ groupSearchFilter
|
||||||
|
+ " in search base '" + groupSearchBase + "'");
|
||||||
|
}
|
||||||
|
|
||||||
DirContext ctx = initialDirContextFactory.newInitialDirContext();
|
DirContext ctx = initialDirContextFactory.newInitialDirContext();
|
||||||
SearchControls ctls = new SearchControls();
|
SearchControls ctls = new SearchControls();
|
||||||
|
|
||||||
|
@ -200,11 +230,15 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
|
throw new LdapDataAccessException("Group search failed for user " + userDn, e);
|
||||||
} finally {
|
} finally {
|
||||||
LdapUtils.closeContext(ctx);
|
LdapUtils.closeContext(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Roles from search: " + userRoles);
|
||||||
|
}
|
||||||
|
|
||||||
return userRoles;
|
return userRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,10 +283,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
this.rolePrefix = rolePrefix;
|
this.rolePrefix = rolePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGroupSearchBase(String groupSearchBase) {
|
|
||||||
this.groupSearchBase = groupSearchBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroupSearchFilter(String groupSearchFilter) {
|
public void setGroupSearchFilter(String groupSearchFilter) {
|
||||||
Assert.notNull(groupSearchFilter, "groupSearchFilter must not be null");
|
Assert.notNull(groupSearchFilter, "groupSearchFilter must not be null");
|
||||||
this.groupSearchFilter = groupSearchFilter;
|
this.groupSearchFilter = groupSearchFilter;
|
||||||
|
@ -272,14 +302,4 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||||
public void setConvertToUpperCase(boolean convertToUpperCase) {
|
public void setConvertToUpperCase(boolean convertToUpperCase) {
|
||||||
this.convertToUpperCase = convertToUpperCase;
|
this.convertToUpperCase = convertToUpperCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
|
|
||||||
this.initialDirContextFactory = initialDirContextFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
if(initialDirContextFactory == null && groupSearchBase != null) {
|
|
||||||
throw new IllegalArgumentException("initialDirContextFactory is required for group role searches.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,20 +30,19 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
idf = new DefaultInitialDirContextFactory();
|
idf = new DefaultInitialDirContextFactory(PROVIDER_URL);
|
||||||
idf.setInitialContextFactory(CONTEXT_FACTORY);
|
idf.setInitialContextFactory(CONTEXT_FACTORY);
|
||||||
idf.setExtraEnvVars(EXTRA_ENV);
|
idf.setExtraEnvVars(EXTRA_ENV);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConnectionFailure() throws Exception {
|
public void testConnectionFailure() throws Exception {
|
||||||
|
|
||||||
idf.setInitialContextFactory("com.sun.jndi.ldap.LdapCtxFactory");
|
|
||||||
// Use the wrong port
|
// Use the wrong port
|
||||||
idf.setUrl("ldap://localhost:60389");
|
idf = new DefaultInitialDirContextFactory("ldap://localhost:60389");
|
||||||
|
idf.setInitialContextFactory("com.sun.jndi.ldap.LdapCtxFactory");
|
||||||
Hashtable env = new Hashtable();
|
Hashtable env = new Hashtable();
|
||||||
env.put("com.sun.jndi.ldap.connect.timeout", "200");
|
env.put("com.sun.jndi.ldap.connect.timeout", "200");
|
||||||
idf.setExtraEnvVars(env);
|
idf.setExtraEnvVars(env);
|
||||||
idf.afterPropertiesSet();
|
|
||||||
try {
|
try {
|
||||||
idf.newInitialDirContext();
|
idf.newInitialDirContext();
|
||||||
fail("Connection succeeded unexpectedly");
|
fail("Connection succeeded unexpectedly");
|
||||||
|
@ -52,8 +51,6 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAnonymousBindSucceeds() throws Exception {
|
public void testAnonymousBindSucceeds() throws Exception {
|
||||||
idf.setUrl(PROVIDER_URL);
|
|
||||||
idf.afterPropertiesSet();
|
|
||||||
DirContext ctx = idf.newInitialDirContext();
|
DirContext ctx = idf.newInitialDirContext();
|
||||||
// Connection pooling should be set by default for anon users.
|
// Connection pooling should be set by default for anon users.
|
||||||
// Can't rely on this property being there with embedded server
|
// Can't rely on this property being there with embedded server
|
||||||
|
@ -62,10 +59,9 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBindAsManagerSucceeds() throws Exception {
|
public void testBindAsManagerSucceeds() throws Exception {
|
||||||
idf.setUrl(PROVIDER_URL);
|
|
||||||
idf.setManagerPassword(MANAGER_PASSWORD);
|
idf.setManagerPassword(MANAGER_PASSWORD);
|
||||||
idf.setManagerDn(MANAGER_USER);
|
idf.setManagerDn(MANAGER_USER);
|
||||||
idf.afterPropertiesSet();
|
|
||||||
DirContext ctx = idf.newInitialDirContext();
|
DirContext ctx = idf.newInitialDirContext();
|
||||||
// Can't rely on this property being there with embedded server
|
// Can't rely on this property being there with embedded server
|
||||||
// assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
// assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool"));
|
||||||
|
@ -73,10 +69,8 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInvalidPasswordCausesBadCredentialsException() throws Exception {
|
public void testInvalidPasswordCausesBadCredentialsException() throws Exception {
|
||||||
idf.setUrl(PROVIDER_URL);
|
|
||||||
idf.setManagerDn(MANAGER_USER);
|
idf.setManagerDn(MANAGER_USER);
|
||||||
idf.setManagerPassword("wrongpassword");
|
idf.setManagerPassword("wrongpassword");
|
||||||
idf.afterPropertiesSet();
|
|
||||||
try {
|
try {
|
||||||
DirContext ctx = idf.newInitialDirContext();
|
DirContext ctx = idf.newInitialDirContext();
|
||||||
fail("Authentication with wrong credentials should fail.");
|
fail("Authentication with wrong credentials should fail.");
|
||||||
|
@ -85,8 +79,6 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConnectionAsSpecificUserSucceeds() throws Exception {
|
public void testConnectionAsSpecificUserSucceeds() throws Exception {
|
||||||
idf.setUrl(PROVIDER_URL);
|
|
||||||
idf.afterPropertiesSet();
|
|
||||||
DirContext ctx = idf.newInitialDirContext("uid=Bob,ou=people,dc=acegisecurity,dc=org",
|
DirContext ctx = idf.newInitialDirContext("uid=Bob,ou=people,dc=acegisecurity,dc=org",
|
||||||
"bobspassword");
|
"bobspassword");
|
||||||
// We don't want pooling for specific users.
|
// We don't want pooling for specific users.
|
||||||
|
@ -95,7 +87,7 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEnvironment() {
|
public void testEnvironment() {
|
||||||
idf.setUrl("ldap://acegisecurity.org/");
|
idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/");
|
||||||
|
|
||||||
// check basic env
|
// check basic env
|
||||||
Hashtable env = idf.getEnvironment();
|
Hashtable env = idf.getEnvironment();
|
||||||
|
@ -124,20 +116,15 @@ public class InitialDirContextFactoryTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBaseDnIsParsedFromCorrectlyFromUrl() throws Exception {
|
public void testBaseDnIsParsedFromCorrectlyFromUrl() throws Exception {
|
||||||
idf.setUrl("ldap://acegisecurity.org/dc=acegisecurity,dc=org");
|
idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/dc=acegisecurity,dc=org");
|
||||||
idf.afterPropertiesSet();
|
|
||||||
assertEquals("dc=acegisecurity,dc=org", idf.getRootDn());
|
assertEquals("dc=acegisecurity,dc=org", idf.getRootDn());
|
||||||
|
|
||||||
// Check with an empty root
|
// Check with an empty root
|
||||||
idf = new DefaultInitialDirContextFactory();
|
idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/");
|
||||||
idf.setUrl("ldap://acegisecurity.org/");
|
|
||||||
idf.afterPropertiesSet();
|
|
||||||
assertEquals("", idf.getRootDn());
|
assertEquals("", idf.getRootDn());
|
||||||
|
|
||||||
// Empty root without trailing slash
|
// Empty root without trailing slash
|
||||||
idf = new DefaultInitialDirContextFactory();
|
idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org");
|
||||||
idf.setUrl("ldap://acegisecurity.org");
|
|
||||||
idf.afterPropertiesSet();
|
|
||||||
assertEquals("", idf.getRootDn());
|
assertEquals("", idf.getRootDn());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,7 @@ import javax.naming.directory.BasicAttributes;
|
||||||
import org.acegisecurity.GrantedAuthority;
|
import org.acegisecurity.GrantedAuthority;
|
||||||
import org.acegisecurity.GrantedAuthorityImpl;
|
import org.acegisecurity.GrantedAuthorityImpl;
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
import org.acegisecurity.Authentication;
|
|
||||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||||
import org.acegisecurity.providers.ldap.authenticator.FilterBasedLdapUserSearch;
|
|
||||||
import org.acegisecurity.providers.ldap.authenticator.BindAuthenticator;
|
|
||||||
import org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator;
|
|
||||||
import org.acegisecurity.userdetails.UserDetails;
|
import org.acegisecurity.userdetails.UserDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,11 +26,8 @@ public class LdapAuthenticationProviderTests extends AbstractLdapServerTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNormalUsage() throws Exception {
|
public void testNormalUsage() throws Exception {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider();
|
LdapAuthenticationProvider ldapProvider
|
||||||
|
= new LdapAuthenticationProvider(new MockAuthenticator(), new MockAuthoritiesPopulator());
|
||||||
ldapProvider.setAuthenticator(new MockAuthenticator());
|
|
||||||
ldapProvider.setLdapAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
|
||||||
ldapProvider.afterPropertiesSet();
|
|
||||||
|
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("bob","bobspassword");
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("bob","bobspassword");
|
||||||
UserDetails user = ldapProvider.retrieveUser("bob", token);
|
UserDetails user = ldapProvider.retrieveUser("bob", token);
|
||||||
|
@ -59,7 +52,7 @@ public class LdapAuthenticationProviderTests extends AbstractLdapServerTestCase
|
||||||
BindAuthenticator authenticator = new BindAuthenticator();
|
BindAuthenticator authenticator = new BindAuthenticator();
|
||||||
//PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator();
|
//PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator();
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
||||||
//authenticator.setUserDnPattern("cn={0},ou=people");
|
//authenticator.setUserDnPatterns("cn={0},ou=people");
|
||||||
|
|
||||||
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch();
|
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch();
|
||||||
userSearch.setSearchBase("ou=people");
|
userSearch.setSearchBase("ou=people");
|
||||||
|
@ -78,7 +71,7 @@ public class LdapAuthenticationProviderTests extends AbstractLdapServerTestCase
|
||||||
populator.setGroupSearchBase("ou=groups");
|
populator.setGroupSearchBase("ou=groups");
|
||||||
populator.afterPropertiesSet();
|
populator.afterPropertiesSet();
|
||||||
|
|
||||||
ldapProvider.setLdapAuthoritiesPopulator(populator);
|
ldapProvider.setAuthoritiesPopulator(populator);
|
||||||
ldapProvider.setAuthenticator(authenticator);
|
ldapProvider.setAuthenticator(authenticator);
|
||||||
Authentication auth = ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("Ben Alex","benspassword"));
|
Authentication auth = ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("Ben Alex","benspassword"));
|
||||||
assertEquals(2, auth.getAuthorities().length);
|
assertEquals(2, auth.getAuthorities().length);
|
||||||
|
@ -94,10 +87,10 @@ public class LdapAuthenticationProviderTests extends AbstractLdapServerTestCase
|
||||||
class MockAuthenticator implements LdapAuthenticator {
|
class MockAuthenticator implements LdapAuthenticator {
|
||||||
Attributes userAttributes = new BasicAttributes("cn","bob");
|
Attributes userAttributes = new BasicAttributes("cn","bob");
|
||||||
|
|
||||||
public LdapUserDetails authenticate(String username, String password) {
|
public LdapUserInfo authenticate(String username, String password) {
|
||||||
if(username.equals("bob") && password.equals("bobspassword")) {
|
if(username.equals("bob") && password.equals("bobspassword")) {
|
||||||
|
|
||||||
return new LdapUserDetails("cn=bob,ou=people,dc=acegisecurity,dc=org", userAttributes);
|
return new LdapUserInfo("cn=bob,ou=people,dc=acegisecurity,dc=org", userAttributes);
|
||||||
}
|
}
|
||||||
throw new BadCredentialsException("Authentication of Bob failed.");
|
throw new BadCredentialsException("Authentication of Bob failed.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,33 +90,6 @@ public class LdapTestServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private void startLdapServer() {
|
|
||||||
// ApplicationContext factory = new ClassPathXmlApplicationContext( "org/acegisecurity/providers/ldap/apacheds-context.xml");
|
|
||||||
// MutableServerStartupConfiguration cfg = ( MutableServerStartupConfiguration ) factory.getBean( "configuration" );
|
|
||||||
// ClassPathResource ldifDir = new ClassPathResource("org/acegisecurity/providers/ldap/ldif");
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// cfg.setLdifDirectory(ldifDir.getFile());
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// System.err.println("Failed to set LDIF directory for server");
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Properties env = ( Properties ) factory.getBean( "environment" );
|
|
||||||
//
|
|
||||||
// env.setProperty( Context.PROVIDER_URL, "dc=acegisecurity,dc=org" );
|
|
||||||
// env.setProperty( Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName() );
|
|
||||||
// env.putAll( cfg.toJndiEnvironment() );
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// serverContext = new InitialDirContext( env );
|
|
||||||
// } catch (NamingException e) {
|
|
||||||
// System.err.println("Failed to start Apache DS");
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void initTestData() {
|
private void initTestData() {
|
||||||
createOu("people");
|
createOu("people");
|
||||||
createOu("groups");
|
createOu("groups");
|
||||||
|
@ -125,7 +98,7 @@ public class LdapTestServer {
|
||||||
String[] developers = new String[]
|
String[] developers = new String[]
|
||||||
{"uid=ben,ou=people,dc=acegisecurity,dc=org", "uid=bob,ou=people,dc=acegisecurity,dc=org"};
|
{"uid=ben,ou=people,dc=acegisecurity,dc=org", "uid=bob,ou=people,dc=acegisecurity,dc=org"};
|
||||||
createGroup("developers","developer",developers);
|
createGroup("developers","developer",developers);
|
||||||
createGroup("managers","manager",new String[] { developers[0]});
|
createGroup("managers","manager", new String[] { developers[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createManagerUser() {
|
private void createManagerUser() {
|
||||||
|
@ -257,5 +230,4 @@ public class LdapTestServer {
|
||||||
LdapTestServer server = new LdapTestServer(false);
|
LdapTestServer server = new LdapTestServer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package org.acegisecurity.providers.ldap.authenticator;
|
package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link BindAuthenticator}.
|
* Tests for {@link BindAuthenticator}.
|
||||||
*
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
|
@ -17,30 +17,26 @@ public class BindAuthenticatorTests extends AbstractLdapServerTestCase {
|
||||||
private BindAuthenticator authenticator;
|
private BindAuthenticator authenticator;
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
dirCtxFactory = new DefaultInitialDirContextFactory();
|
dirCtxFactory = new DefaultInitialDirContextFactory(PROVIDER_URL);
|
||||||
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
||||||
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
||||||
dirCtxFactory.setUrl(PROVIDER_URL);
|
authenticator = new BindAuthenticator(dirCtxFactory);
|
||||||
dirCtxFactory.afterPropertiesSet();
|
|
||||||
authenticator = new BindAuthenticator();
|
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUserDnPatternReturnsCorrectDn() throws Exception {
|
public void testUserDnPatternReturnsCorrectDn() throws Exception {
|
||||||
authenticator.setUserDnPattern("cn={0},ou=people");
|
authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"});
|
||||||
assertEquals("cn=Joe,ou=people,"+ ROOT_DN, authenticator.getUserDn("Joe"));
|
assertEquals("cn=Joe,ou=people,"+ ROOT_DN, authenticator.getUserDns("Joe").get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationWithCorrectPasswordSucceeds() throws Exception {
|
public void testAuthenticationWithCorrectPasswordSucceeds() throws Exception {
|
||||||
authenticator.setUserDnPattern("uid={0},ou=people");
|
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
||||||
LdapUserDetails user = authenticator.authenticate("bob","bobspassword");
|
LdapUserInfo user = authenticator.authenticate("bob","bobspassword");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationWithWrongPasswordFails() {
|
public void testAuthenticationWithWrongPasswordFails() {
|
||||||
BindAuthenticator authenticator = new BindAuthenticator();
|
BindAuthenticator authenticator = new BindAuthenticator(dirCtxFactory);
|
||||||
|
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
||||||
authenticator.setUserDnPattern("uid={0},ou=people");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
authenticator.authenticate("bob","wrongpassword");
|
authenticator.authenticate("bob","wrongpassword");
|
||||||
|
@ -50,7 +46,7 @@ public class BindAuthenticatorTests extends AbstractLdapServerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationWithUserSearch() throws Exception {
|
public void testAuthenticationWithUserSearch() throws Exception {
|
||||||
LdapUserDetails user = new LdapUserDetails("uid=bob,ou=people," + ROOT_DN, null);
|
LdapUserInfo user = new LdapUserInfo("uid=bob,ou=people," + ROOT_DN, null);
|
||||||
authenticator.setUserSearch(new MockUserSearch(user));
|
authenticator.setUserSearch(new MockUserSearch(user));
|
||||||
authenticator.afterPropertiesSet();
|
authenticator.afterPropertiesSet();
|
||||||
authenticator.authenticate("bob","bobspassword");
|
authenticator.authenticate("bob","bobspassword");
|
||||||
|
@ -63,7 +59,7 @@ public class BindAuthenticatorTests extends AbstractLdapServerTestCase {
|
||||||
// BindAuthenticator authenticator = new BindAuthenticator();
|
// BindAuthenticator authenticator = new BindAuthenticator();
|
||||||
//
|
//
|
||||||
// authenticator.setInitialDirContextFactory(dirCtxFactory);
|
// authenticator.setInitialDirContextFactory(dirCtxFactory);
|
||||||
// authenticator.setUserDnPattern("cn={0},ou=people");
|
// authenticator.setUserDnPatterns("cn={0},ou=people");
|
||||||
// try {
|
// try {
|
||||||
// authenticator.authenticate("Baz","bobspassword");
|
// authenticator.authenticate("Baz","bobspassword");
|
||||||
// fail("Shouldn't be able to bind with invalid username");
|
// fail("Shouldn't be able to bind with invalid username");
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
||||||
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
|
|
||||||
|
@ -17,13 +17,11 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapServerTestCase {
|
||||||
private FilterBasedLdapUserSearch locator;
|
private FilterBasedLdapUserSearch locator;
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
dirCtxFactory = new DefaultInitialDirContextFactory();
|
dirCtxFactory = new DefaultInitialDirContextFactory(PROVIDER_URL);
|
||||||
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
||||||
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
||||||
dirCtxFactory.setUrl(PROVIDER_URL);
|
|
||||||
dirCtxFactory.setManagerDn(MANAGER_USER);
|
dirCtxFactory.setManagerDn(MANAGER_USER);
|
||||||
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
||||||
dirCtxFactory.afterPropertiesSet();
|
|
||||||
locator = new FilterBasedLdapUserSearch();
|
locator = new FilterBasedLdapUserSearch();
|
||||||
locator.setSearchSubtree(false);
|
locator.setSearchSubtree(false);
|
||||||
locator.setSearchTimeLimit(0);
|
locator.setSearchTimeLimit(0);
|
||||||
|
@ -42,7 +40,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapServerTestCase {
|
||||||
locator.setSearchBase("ou=people");
|
locator.setSearchBase("ou=people");
|
||||||
locator.setSearchFilter("(uid={0})");
|
locator.setSearchFilter("(uid={0})");
|
||||||
locator.afterPropertiesSet();
|
locator.afterPropertiesSet();
|
||||||
LdapUserDetails bob = locator.searchForUser("bob");
|
LdapUserInfo bob = locator.searchForUser("bob");
|
||||||
// name is wrong with embedded apacheDS
|
// name is wrong with embedded apacheDS
|
||||||
// assertEquals("uid=bob,ou=people,"+ROOT_DN, bob.getDn());
|
// assertEquals("uid=bob,ou=people,"+ROOT_DN, bob.getDn());
|
||||||
}
|
}
|
||||||
|
@ -52,7 +50,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapServerTestCase {
|
||||||
locator.setSearchFilter("(cn={0})");
|
locator.setSearchFilter("(cn={0})");
|
||||||
locator.setSearchSubtree(true);
|
locator.setSearchSubtree(true);
|
||||||
locator.afterPropertiesSet();
|
locator.afterPropertiesSet();
|
||||||
LdapUserDetails ben = locator.searchForUser("Ben Alex");
|
LdapUserInfo ben = locator.searchForUser("Ben Alex");
|
||||||
// assertEquals("uid=ben,ou=people,"+ROOT_DN, bob.getDn());
|
// assertEquals("uid=ben,ou=people,"+ROOT_DN, bob.getDn());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,10 +80,10 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapServerTestCase {
|
||||||
|
|
||||||
public void testExtraFilterPartToExcludeBob() throws Exception {
|
public void testExtraFilterPartToExcludeBob() throws Exception {
|
||||||
locator.setSearchBase("ou=people");
|
locator.setSearchBase("ou=people");
|
||||||
locator.setSearchFilter("(&(cn=*)(!(uid={0})))");
|
locator.setSearchFilter("(&(cn=*)(!(|(uid={0})(uid=marissa))))");
|
||||||
|
|
||||||
// Search for bob, get back ben...
|
// Search for bob, get back ben...
|
||||||
LdapUserDetails ben = locator.searchForUser("bob");
|
LdapUserInfo ben = locator.searchForUser("bob");
|
||||||
String cn = (String)ben.getAttributes().get("cn").get();
|
String cn = (String)ben.getAttributes().get("cn").get();
|
||||||
assertEquals("Ben Alex", cn);
|
assertEquals("Ben Alex", cn);
|
||||||
// assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn());
|
// assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn());
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package org.acegisecurity.providers.ldap.authenticator;
|
package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class MockUserSearch implements LdapUserSearch {
|
public class MockUserSearch implements LdapUserSearch {
|
||||||
LdapUserDetails user;
|
LdapUserInfo user;
|
||||||
|
|
||||||
public MockUserSearch(LdapUserDetails user) {
|
public MockUserSearch(LdapUserInfo user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LdapUserDetails searchForUser(String username) {
|
public LdapUserInfo searchForUser(String username) {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,14 @@ public class PasswordComparisonAuthenticatorMockTests extends MockObjectTestCase
|
||||||
public void testLdapCompareIsUsedWhenPasswordIsNotRetrieved() throws Exception {
|
public void testLdapCompareIsUsedWhenPasswordIsNotRetrieved() throws Exception {
|
||||||
Mock mockCtx = new Mock(DirContext.class);
|
Mock mockCtx = new Mock(DirContext.class);
|
||||||
|
|
||||||
PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator();
|
PasswordComparisonAuthenticator authenticator =
|
||||||
authenticator.setUserDnPattern("cn={0},ou=people");
|
new PasswordComparisonAuthenticator(new MockInitialDirContextFactory(
|
||||||
authenticator.setInitialDirContextFactory(
|
(DirContext)mockCtx.proxy(),
|
||||||
new MockInitialDirContextFactory((DirContext)mockCtx.proxy(),
|
"dc=acegisecurity,dc=org")
|
||||||
"dc=acegisecurity,dc=org"));
|
);
|
||||||
|
|
||||||
|
authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"});
|
||||||
|
|
||||||
// Get the mock to return an empty attribute set
|
// Get the mock to return an empty attribute set
|
||||||
mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=acegisecurity,dc=org"));
|
mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=acegisecurity,dc=org"));
|
||||||
mockCtx.expects(once()).method("getAttributes").with(eq("cn=Bob,ou=people"), NULL).will(returnValue(new BasicAttributes()));
|
mockCtx.expects(once()).method("getAttributes").with(eq("cn=Bob,ou=people"), NULL).will(returnValue(new BasicAttributes()));
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package org.acegisecurity.providers.ldap.authenticator;
|
package org.acegisecurity.providers.ldap.authenticator;
|
||||||
|
|
||||||
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
import org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory;
|
||||||
import org.acegisecurity.providers.ldap.LdapUserDetails;
|
import org.acegisecurity.providers.ldap.LdapUserInfo;
|
||||||
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
import org.acegisecurity.providers.ldap.AbstractLdapServerTestCase;
|
||||||
import org.acegisecurity.providers.encoding.PlaintextPasswordEncoder;
|
|
||||||
import org.acegisecurity.BadCredentialsException;
|
import org.acegisecurity.BadCredentialsException;
|
||||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||||
|
|
||||||
import javax.naming.directory.BasicAttributes;
|
import javax.naming.directory.BasicAttributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link PasswordComparisonAuthenticator}.
|
||||||
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
@ -18,17 +19,13 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
private PasswordComparisonAuthenticator authenticator;
|
private PasswordComparisonAuthenticator authenticator;
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// Connection information
|
dirCtxFactory = new DefaultInitialDirContextFactory(PROVIDER_URL);
|
||||||
dirCtxFactory = new DefaultInitialDirContextFactory();
|
|
||||||
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
||||||
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
||||||
dirCtxFactory.setUrl(PROVIDER_URL);
|
|
||||||
dirCtxFactory.setManagerDn(MANAGER_USER);
|
dirCtxFactory.setManagerDn(MANAGER_USER);
|
||||||
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
||||||
dirCtxFactory.afterPropertiesSet();
|
authenticator = new PasswordComparisonAuthenticator(dirCtxFactory);
|
||||||
authenticator = new PasswordComparisonAuthenticator();
|
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
|
||||||
authenticator.setUserDnPattern("uid={0},ou=people");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
@ -46,7 +43,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
public void testLdapCompareSucceedsWithShaEncodedPassword() {
|
public void testLdapCompareSucceedsWithShaEncodedPassword() {
|
||||||
authenticator = new PasswordComparisonAuthenticator();
|
authenticator = new PasswordComparisonAuthenticator();
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
||||||
authenticator.setUserDnPattern("uid={0},ou=people");
|
authenticator.setUserDnPatterns("uid={0},ou=people");
|
||||||
// Don't retrieve the password
|
// Don't retrieve the password
|
||||||
authenticator.setUserAttributes(new String[] {"cn"});
|
authenticator.setUserAttributes(new String[] {"cn"});
|
||||||
authenticator.authenticate("ben", "benspassword");
|
authenticator.authenticate("ben", "benspassword");
|
||||||
|
@ -76,9 +73,8 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLocalCompareSucceedsWithShaEncodedPassword() {
|
public void testLocalCompareSucceedsWithShaEncodedPassword() {
|
||||||
authenticator = new PasswordComparisonAuthenticator();
|
authenticator = new PasswordComparisonAuthenticator(dirCtxFactory);
|
||||||
authenticator.setInitialDirContextFactory(dirCtxFactory);
|
authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"});
|
||||||
authenticator.setUserDnPattern("uid={0},ou=people");
|
|
||||||
authenticator.authenticate("ben", "benspassword");
|
authenticator.authenticate("ben", "benspassword");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +87,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAllAttributesAreRetrivedByDefault() {
|
public void testAllAttributesAreRetrivedByDefault() {
|
||||||
LdapUserDetails user = authenticator.authenticate("Bob", "bobspassword");
|
LdapUserInfo user = authenticator.authenticate("Bob", "bobspassword");
|
||||||
System.out.println(user.getAttributes().toString());
|
System.out.println(user.getAttributes().toString());
|
||||||
assertEquals("User should have 5 attributes", 5, user.getAttributes().size());
|
assertEquals("User should have 5 attributes", 5, user.getAttributes().size());
|
||||||
|
|
||||||
|
@ -100,7 +96,7 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
public void testOnlySpecifiedAttributesAreRetrieved() throws Exception {
|
public void testOnlySpecifiedAttributesAreRetrieved() throws Exception {
|
||||||
authenticator.setUserAttributes(new String[] {"cn", "uid"});
|
authenticator.setUserAttributes(new String[] {"cn", "uid"});
|
||||||
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
authenticator.setPasswordEncoder(new PlaintextPasswordEncoder());
|
||||||
LdapUserDetails user = authenticator.authenticate("Bob", "bobspassword");
|
LdapUserInfo user = authenticator.authenticate("Bob", "bobspassword");
|
||||||
assertEquals("Should have retrieved 2 attributes (cn, uid)",2, user.getAttributes().size());
|
assertEquals("Should have retrieved 2 attributes (cn, uid)",2, user.getAttributes().size());
|
||||||
assertEquals("Bob Hamilton", user.getAttributes().get("cn").get());
|
assertEquals("Bob Hamilton", user.getAttributes().get("cn").get());
|
||||||
assertEquals("bob", user.getAttributes().get("uid").get());
|
assertEquals("bob", user.getAttributes().get("uid").get());
|
||||||
|
@ -120,17 +116,19 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void testWithUserSearch() {
|
public void testWithUserSearch() {
|
||||||
LdapUserDetails user = new LdapUserDetails("uid=Bob,ou=people" + ROOT_DN,
|
authenticator = new PasswordComparisonAuthenticator(dirCtxFactory);
|
||||||
|
assertTrue("User DN matches shouldn't be available",
|
||||||
|
authenticator.getUserDns("Bob").isEmpty());
|
||||||
|
LdapUserInfo user = new LdapUserInfo("uid=Bob,ou=people" + ROOT_DN,
|
||||||
new BasicAttributes("userPassword","bobspassword"));
|
new BasicAttributes("userPassword","bobspassword"));
|
||||||
authenticator.setUserDnPattern(null);
|
|
||||||
assertNull(authenticator.getUserDnPattern());
|
|
||||||
assertNull(authenticator.getUserDn("Bob"));
|
|
||||||
authenticator.setUserSearch(new MockUserSearch(user));
|
authenticator.setUserSearch(new MockUserSearch(user));
|
||||||
authenticator.authenticate("ShouldntBeUsed","bobspassword");
|
authenticator.authenticate("ShouldntBeUsed","bobspassword");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFailedSearchGivesUserNotFoundException() throws Exception {
|
public void testFailedSearchGivesUserNotFoundException() throws Exception {
|
||||||
authenticator.setUserDnPattern(null);
|
authenticator = new PasswordComparisonAuthenticator(dirCtxFactory);
|
||||||
|
assertTrue("User DN matches shouldn't be available",
|
||||||
|
authenticator.getUserDns("Bob").isEmpty());
|
||||||
authenticator.setUserSearch(new MockUserSearch(null));
|
authenticator.setUserSearch(new MockUserSearch(null));
|
||||||
authenticator.afterPropertiesSet();
|
authenticator.afterPropertiesSet();
|
||||||
|
|
||||||
|
|
|
@ -17,31 +17,17 @@ import java.util.HashSet;
|
||||||
*/
|
*/
|
||||||
public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapServerTestCase {
|
public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapServerTestCase {
|
||||||
private DefaultInitialDirContextFactory dirCtxFactory;
|
private DefaultInitialDirContextFactory dirCtxFactory;
|
||||||
private DefaultLdapAuthoritiesPopulator populator;
|
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
dirCtxFactory = new DefaultInitialDirContextFactory();
|
dirCtxFactory = new DefaultInitialDirContextFactory(PROVIDER_URL);
|
||||||
dirCtxFactory.setUrl(PROVIDER_URL);
|
|
||||||
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
dirCtxFactory.setInitialContextFactory(CONTEXT_FACTORY);
|
||||||
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
dirCtxFactory.setExtraEnvVars(EXTRA_ENV);
|
||||||
dirCtxFactory.setManagerDn(MANAGER_USER);
|
dirCtxFactory.setManagerDn(MANAGER_USER);
|
||||||
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
dirCtxFactory.setManagerPassword(MANAGER_PASSWORD);
|
||||||
|
|
||||||
populator = new DefaultLdapAuthoritiesPopulator();
|
|
||||||
populator.setRolePrefix("ROLE_");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCtxFactoryMustBeSetIfSearchBaseIsSet() throws Exception {
|
|
||||||
populator.setGroupSearchBase("");
|
|
||||||
|
|
||||||
try {
|
|
||||||
populator.afterPropertiesSet();
|
|
||||||
fail("expected exception.");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUserAttributeMappingToRoles() {
|
public void testUserAttributeMappingToRoles() {
|
||||||
|
DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator();
|
||||||
populator.setUserRoleAttributes(new String[] {"userRole", "otherUserRole"});
|
populator.setUserRoleAttributes(new String[] {"userRole", "otherUserRole"});
|
||||||
populator.getUserRoleAttributes();
|
populator.getUserRoleAttributes();
|
||||||
|
|
||||||
|
@ -58,14 +44,13 @@ public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapServerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGroupSearch() throws Exception {
|
public void testGroupSearch() throws Exception {
|
||||||
populator.setInitialDirContextFactory(dirCtxFactory);
|
DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(dirCtxFactory, "ou=groups");
|
||||||
populator.setGroupSearchBase("ou=groups");
|
populator.setRolePrefix("ROLE_");
|
||||||
populator.setGroupRoleAttribute("ou");
|
populator.setGroupRoleAttribute("ou");
|
||||||
populator.setSearchSubtree(true);
|
populator.setSearchSubtree(true);
|
||||||
populator.setSearchSubtree(false);
|
populator.setSearchSubtree(false);
|
||||||
populator.setConvertToUpperCase(true);
|
populator.setConvertToUpperCase(true);
|
||||||
populator.setGroupSearchFilter("(member={0})");
|
populator.setGroupSearchFilter("(member={0})");
|
||||||
populator.afterPropertiesSet();
|
|
||||||
|
|
||||||
GrantedAuthority[] authorities = populator.getGrantedAuthorities("ben", "uid=ben,ou=people,"+ROOT_DN, new BasicAttributes());
|
GrantedAuthority[] authorities = populator.getGrantedAuthorities("ben", "uid=ben,ou=people,"+ROOT_DN, new BasicAttributes());
|
||||||
assertEquals("Should have 2 roles", 2, authorities.length);
|
assertEquals("Should have 2 roles", 2, authorities.length);
|
||||||
|
|
Loading…
Reference in New Issue