All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.acegisecurity.ldap.DefaultInitialDirContextFactory Maven / Gradle / Ivy

There is a newer version: 1.0.7
Show newest version
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.acegisecurity.ldap;

import org.acegisecurity.AcegiMessageSource;
import org.acegisecurity.BadCredentialsException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;

import org.springframework.util.Assert;

import java.util.Hashtable;
import java.util.Map;
import java.util.StringTokenizer;

import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;


/**
 * Encapsulates the information for connecting to an LDAP server and provides an access point for obtaining
 * DirContext references.

The directory location is configured using by setting the constructor argument * providerUrl. This should be in the form ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org. * The Sun JNDI provider also supports lists of space-separated URLs, each of which will be tried in turn until a * connection is obtained.

*

To obtain an initial context, the client calls the newInitialDirContext method. There are two * signatures - one with no arguments and one which allows binding with a specific username and password.

*

The no-args version will bind anonymously unless a manager login has been configured using the properties * managerDn and managerPassword, in which case it will bind as the manager user.

*

Connection pooling is enabled by default for anonymous or manager connections, but not when binding as a * specific user.

* * @author Robert Sanders * @author Luke Taylor * @version $Id: DefaultInitialDirContextFactory.java 1498 2006-05-26 22:48:21Z luke_t $ * * @see The Java tutorial's guide to LDAP * connection pooling */ public class DefaultInitialDirContextFactory implements InitialDirContextFactory, MessageSourceAware { //~ 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 ================================================================================================ /** Allows extra environment variables to be added at config time. */ private Map extraEnvVars = null; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); /** 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 should not need to set this unless you have unusual needs. */ private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; /** * 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"; /** The LDAP url of the server (and root context) to connect to. */ private String providerUrl; /** * 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 = 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 providerUrl) { this.providerUrl = providerUrl; Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied."); StringTokenizer st = new StringTokenizer(providerUrl); // Work out rootDn from the first URL and check that the other URLs (if any) match while (st.hasMoreTokens()) { String url = st.nextToken(); String urlRootDn = LdapUtils.parseRootDnFromUrl(url); logger.info(" URL '" + url + "', root DN is '" + urlRootDn + "'"); if (rootDn == null) { rootDn = urlRootDn; } else if (!rootDn.equals(urlRootDn)) { throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs"); } } // This doesn't necessarily hold for embedded servers. //Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'"); } //~ Methods ======================================================================================================== 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); } } /** * Sets up the environment parameters for creating a new context. * * @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, providerUrl); if (useConnectionPool) { env.put(CONNECTION_POOL_KEY, "true"); } if ((extraEnvVars != null) && (extraEnvVars.size() > 0)) { env.putAll(extraEnvVars); } return env; } /** * Returns the root DN of the configured provider URL. For example, if the URL is * ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org the value will be * dc=acegisecurity,dc=org. * * @return the root DN calculated from the path of the LDAP url. */ public String getRootDn() { return rootDn; } /** * 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); } public void setAuthenticationType(String authenticationType) { Assert.hasLength(authenticationType, "LDAP Authentication type must not be empty or null"); this.authenticationType = authenticationType; } /** * Sets any custom environment variables which will be added to the those returned * by the getEnvironment method. * * @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 setInitialContextFactory(String initialContextFactory) { Assert.hasLength(initialContextFactory, "Initial context factory name cannot be empty or null"); this.initialContextFactory = initialContextFactory; } /** * Sets the directory user to authenticate as when obtaining a context using the * newInitialDirContext() method. * If no name is supplied then the context will be obtained anonymously. * * @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; } /** * Sets the password which will be used in combination with the manager DN. * * @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; } 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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy