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

org.acegisecurity.providers.ldap.LdapAuthenticationProvider 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.providers.ldap;

import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.AuthenticationServiceException;

import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;

import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.ldap.LdapUserDetails;
import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl;

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

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.dao.DataAccessException;


/**
 * An {@link org.acegisecurity.providers.AuthenticationProvider} implementation that provides integration with an
 * LDAP server.
 *
 * 

There are many ways in which an LDAP directory can be configured so this class delegates most of * its responsibilites to two separate strategy interfaces, {@link LdapAuthenticator} * and {@link LdapAuthoritiesPopulator}.

* *

LdapAuthenticator

* This interface is responsible for performing the user authentication and retrieving * the user's information from the directory. Example implementations are {@link * org.acegisecurity.providers.ldap.authenticator.BindAuthenticator BindAuthenticator} which authenticates the user by * "binding" as that user, and {@link org.acegisecurity.providers.ldap.authenticator.PasswordComparisonAuthenticator * PasswordComparisonAuthenticator} which performs a comparison of the supplied password with the value stored in the * directory, either by retrieving the password or performing an LDAP "compare" operation. *

The task of retrieving the user attributes is delegated to the authenticator because the permissions on the * attributes may depend on the type of authentication being used; for example, if binding as the user, it may be * necessary to read them with the user's own permissions (using the same context used for the bind operation).

* *

LdapAuthoritiesPopulator

* Once the user has been authenticated, this interface is called to obtain the set of granted authorities for the * user. * The * {@link org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator DefaultLdapAuthoritiesPopulator} * can be configured to obtain user role information from the user's attributes and/or to perform a search for * "groups" that the user is a member of and map these to roles. * *

A custom implementation could obtain the roles from a completely different source, for example from a database. *

* *

Configuration

A simple configuration might be as follows: *
 *    <bean id="initialDirContextFactory" class="org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory">
 *      <constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/>
 *      <property name="managerDn"><value>cn=manager,dc=acegisecurity,dc=org</value></property>
 *      <property name="managerPassword"><value>password</value></property>
 *    </bean>
 *
 *    <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
 *      <constructor-arg>
 *        <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
 *          <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
 *          <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
 *        </bean>
 *      </constructor-arg>
 *      <constructor-arg>
 *        <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
 *          <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
 *          <constructor-arg><value>ou=groups</value></constructor-arg>
 *          <property name="groupRoleAttribute"><value>ou</value></property>
 *        </bean>
 *      </constructor-arg>
 *    </bean>
* *

This would set up the provider to access an LDAP server with URL * ldap://monkeymachine:389/dc=acegisecurity,dc=org. Authentication will be performed by attempting to bind * with the DN uid=<user-login-name>,ou=people,dc=acegisecurity,dc=org. After successful * authentication, roles will be assigned to the user by searching under the DN * ou=groups,dc=acegisecurity,dc=org with the default filter (member=<user's-DN>). The role * name will be taken from the "ou" attribute of each match.

*

* The authenticate method will reject empty passwords outright. LDAP servers may allow an anonymous * bind operation with an empty password, even if a DN is supplied. In practice this means that if * the LDAP directory is configured to allow unauthenitcated access, it might be possible to * authenticate as any user just by supplying an empty password. * More information on the misuse of unauthenticated access can be found in * * draft-ietf-ldapbis-authmeth-19.txt. *

* * @author Luke Taylor * @version $Id: LdapAuthenticationProvider.java 1585 2006-07-20 13:15:55Z carlossg $ * * @see org.acegisecurity.providers.ldap.authenticator.BindAuthenticator * @see org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator */ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LdapAuthenticationProvider.class); //~ Instance fields ================================================================================================ private LdapAuthenticator authenticator; private LdapAuthoritiesPopulator authoritiesPopulator; //~ Constructors =================================================================================================== /** * Create an initialized instance to the values passed as arguments * * @param authenticator * @param authoritiesPopulator */ public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(authoritiesPopulator); } //~ Methods ======================================================================================================== private void setAuthenticator(LdapAuthenticator authenticator) { Assert.notNull(authenticator, "An LdapAuthenticator must be supplied"); this.authenticator = authenticator; } private LdapAuthenticator getAuthenticator() { return authenticator; } private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied"); this.authoritiesPopulator = authoritiesPopulator; } protected LdapAuthoritiesPopulator getAuthoritiesPopulator() { return authoritiesPopulator; } protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (!userDetails.getPassword().equals(authentication.getCredentials().toString())) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails); } } /** * Creates the final UserDetails object that will be returned by the provider once the user has * been authenticated.

The LdapAuthoritiesPopulator will be used to create the granted * authorites for the user.

*

Can be overridden to customize the creation of the final UserDetails instance. The default will * merge any additional authorities retrieved from the populator with the propertis of original ldapUser * object and set the values of the username and password.

* * @param ldapUser The intermediate LdapUserDetails instance returned by the authenticator. * @param username the username submitted to the provider * @param password the password submitted to the provider * * @return The UserDetails for the successfully authenticated user. */ protected UserDetails createUserDetails(LdapUserDetails ldapUser, String username, String password) { LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(ldapUser); user.setUsername(username); user.setPassword(password); GrantedAuthority[] extraAuthorities = getAuthoritiesPopulator().getGrantedAuthorities(ldapUser); for (int i = 0; i < extraAuthorities.length; i++) { user.addAuthority(extraAuthorities[i]); } return user.createUserDetails(); } protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (!StringUtils.hasLength(username)) { throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyUsername", "Empty Username")); } if (logger.isDebugEnabled()) { logger.debug("Retrieving user " + username); } String password = (String) authentication.getCredentials(); Assert.notNull(password, "Null password was supplied in authentication token"); if (password.length() == 0) { logger.debug("Rejecting empty password for user " + username); throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyPassword", "Empty Password")); } try { LdapUserDetails ldapUser = getAuthenticator().authenticate(username, password); return createUserDetails(ldapUser, username, password); } catch (DataAccessException ldapAccessFailure) { throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy