@ -15,282 +15,21 @@
@@ -15,282 +15,21 @@
package org.acegisecurity.providers.ldap ;
import java.util.Hashtable ;
import java.util.Map ;
import java.net.URI ;
import javax.naming.Context ;
import javax.naming.NamingException ;
import javax.naming.CommunicationException ;
import javax.naming.directory.InitialDirContext ;
import javax.naming.directory.DirContext ;
import org.springframework.util.Assert ;
import org.springframework.context.MessageSourceAware ;
import org.springframework.context.MessageSource ;
import org.springframework.context.support.MessageSourceAccessor ;
import org.acegisecurity.BadCredentialsException ;
import org.acegisecurity.AcegiMessageSource ;
import org.apache.commons.logging.Log ;
import org.apache.commons.logging.LogFactory ;
/ * *
* Encapsulates the information for connecting to an LDAP server and provides an
* access point for obtaining < tt > DirContext < / tt > references .
* < p >
* The directory location is configured using by setting the < tt > url < / tt > property .
* This should be in the form < tt > ldap : //monkeymachine.co.uk:389/dc=acegisecurity,dc=org</tt>.
* < / p >
* < p >
* 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
* binding with a specific username and password .
* < / p >
* < p >
* The no - args version will bind anonymously unless a manager login has been configured
* using the properties < tt > managerDn < / tt > and < tt > managerPassword < / tt > , in which case
* it will bind as the manager user .
* < / p >
* < p >
* Connection pooling is enabled by default for anonymous or manager connections , but
* not when binding as a specific user .
* < / p >
*
* @see < a href = "http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html" > The Java
* tutorial ' s guide to LDAP connection pooling < / a >
* @deprecated moved to org . acegisecurity . ldap
*
* @author Robert Sanders
* @author Luke Taylor
* @version $Id$
*
* /
public class DefaultInitialDirContextFactory implements InitialDirContextFactory ,
MessageSourceAware {
public class DefaultInitialDirContextFactory extends org . acegisecurity . ldap . DefaultInitialDirContextFactory {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory . getLog ( DefaultInitialDirContextFactory . class ) ;
private static final String CONNECTION_POOL_KEY = "com.sun.jndi.ldap.connect.pool" ;
private static final String AUTH_TYPE_NONE = "none" ;
//~ Instance fields ========================================================
protected MessageSourceAccessor messages = AcegiMessageSource . getAccessor ( ) ;
/ * *
* The LDAP url of the server ( and root context ) to connect to .
* TODO : Allow a backup URL for a replication server .
* /
private String url ;
/ * *
* The root DN . This is worked out from the url .
* It is used by client classes when forming a full DN for
* bind authentication ( for example ) .
* /
private String rootDn ;
/ * *
* If your LDAP server does not allow anonymous searches then
* you will need to provide a "manager" user ' s DN to log in with .
* /
private String managerDn = null ;
/ * *
* The manager user ' s password .
* /
private String managerPassword = "manager_password_not_set" ;
/** Type of authentication within LDAP; default is simple. */
private String authenticationType = "simple" ;
/ * *
* The INITIAL_CONTEXT_FACTORY used to create the JNDI Factory .
* Default is "com.sun.jndi.ldap.LdapCtxFactory" ; you < b > should not < / b >
* need to set this unless you have unusual needs .
* /
private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory" ;
/** Allows extra environment variables to be added at config time. */
private Map extraEnvVars = null ;
/ * *
* Use the LDAP Connection pool ; if true , then the
* LDAP environment property "com.sun.jndi.ldap.connect.pool" is added
* to any other JNDI properties .
* /
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:" ) | | url . startsWith ( "ldaps:" ) ) {
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 ================================================================
/ * *
* Connects anonymously unless a manager user has been specified , in which case
* it will bind as the manager .
*
* @return the resulting context object .
* /
public DirContext newInitialDirContext ( ) {
if ( managerDn ! = null ) {
return newInitialDirContext ( managerDn , managerPassword ) ;
}
Hashtable env = getEnvironment ( ) ;
env . put ( Context . SECURITY_AUTHENTICATION , AUTH_TYPE_NONE ) ;
return connect ( env ) ;
}
public DirContext newInitialDirContext ( String username , String password ) {
Hashtable env = getEnvironment ( ) ;
// Don't pool connections for individual users
if ( ! username . equals ( managerDn ) ) {
env . remove ( CONNECTION_POOL_KEY ) ;
}
env . put ( Context . SECURITY_PRINCIPAL , username ) ;
env . put ( Context . SECURITY_CREDENTIALS , password ) ;
return connect ( env ) ;
}
/ * *
* @return the Hashtable describing the base DirContext that will be created ,
* minus the username / password if any .
* /
protected Hashtable getEnvironment ( ) {
Hashtable env = new Hashtable ( ) ;
env . put ( Context . SECURITY_AUTHENTICATION , authenticationType ) ;
env . put ( Context . INITIAL_CONTEXT_FACTORY , initialContextFactory ) ;
env . put ( Context . PROVIDER_URL , url ) ;
if ( useConnectionPool ) {
env . put ( CONNECTION_POOL_KEY , "true" ) ;
}
if ( ( extraEnvVars ! = null ) & & ( extraEnvVars . size ( ) > 0 ) ) {
env . putAll ( extraEnvVars ) ;
}
return env ;
}
private InitialDirContext connect ( Hashtable env ) {
if ( logger . isDebugEnabled ( ) ) {
Hashtable envClone = ( Hashtable ) env . clone ( ) ;
if ( envClone . containsKey ( Context . SECURITY_CREDENTIALS ) ) {
envClone . put ( Context . SECURITY_CREDENTIALS , "******" ) ;
}
logger . debug ( "Creating InitialDirContext with environment " + envClone ) ;
}
try {
return new InitialDirContext ( env ) ;
} catch ( CommunicationException ce ) {
throw new LdapDataAccessException ( messages . getMessage (
"DefaultIntitalDirContextFactory.communicationFailure" ,
"Unable to connect to LDAP server" ) , ce ) ;
} catch ( javax . naming . AuthenticationException ae ) {
throw new BadCredentialsException ( messages . getMessage (
"DefaultIntitalDirContextFactory.badCredentials" ,
"Bad credentials" ) , ae ) ;
} catch ( NamingException nx ) {
throw new LdapDataAccessException ( messages . getMessage (
"DefaultIntitalDirContextFactory.unexpectedException" ,
"Failed to obtain InitialDirContext due to unexpected exception" ) , nx ) ;
}
}
/ * *
* 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>
* the value will be < tt > dc = acegisecurity , dc = org < / tt > .
*
* @return the root DN calculated from the path of the LDAP url .
* /
public String getRootDn ( ) {
return rootDn ;
}
public void setAuthenticationType ( String authenticationType ) {
Assert . hasLength ( authenticationType , "LDAP Authentication type must not be empty or null" ) ;
this . authenticationType = authenticationType ;
}
public void setInitialContextFactory ( String initialContextFactory ) {
Assert . hasLength ( initialContextFactory , "Initial context factory name cannot be empty or null" ) ;
this . initialContextFactory = initialContextFactory ;
}
/ * *
* @param managerDn The name of the "manager" user for default authentication .
* /
public void setManagerDn ( String managerDn ) {
Assert . hasLength ( managerDn , "Manager user name cannot be empty or null." ) ;
this . managerDn = managerDn ;
}
/ * *
* @param managerPassword The "manager" user ' s password .
* /
public void setManagerPassword ( String managerPassword ) {
Assert . hasLength ( managerPassword , "Manager password must not be empty or null." ) ;
this . managerPassword = managerPassword ;
}
/ * *
* @param extraEnvVars extra environment variables to be added at config time .
* /
public void setExtraEnvVars ( Map extraEnvVars ) {
Assert . notNull ( extraEnvVars , "Extra environment map cannot be null." ) ;
this . extraEnvVars = extraEnvVars ;
}
public void setMessageSource ( MessageSource messageSource ) {
this . messages = new MessageSourceAccessor ( messageSource ) ;
}
/ * *
* Connection pooling is enabled by default for anonymous or "manager"
* connections when using the default Sun provider . To disable all
* connection pooling , set this property to false .
*
* @param useConnectionPool whether to pool connections for non - specific users .
* /
public void setUseConnectionPool ( boolean useConnectionPool ) {
this . useConnectionPool = useConnectionPool ;
public DefaultInitialDirContextFactory ( String providerUrl ) {
super ( providerUrl ) ;
}
}