spring security LdapAuthenticationProvider 源码

  • 2022-08-13
  • 浏览 (431)

spring security LdapAuthenticationProvider 代码

文件路径:/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java

/*
 * 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
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.security.ldap.authentication;

import java.util.Collection;

import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.ppolicy.PasswordPolicyException;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
import org.springframework.util.Assert;

/**
 * An {@link org.springframework.security.authentication.AuthenticationProvider}
 * implementation that authenticates against an LDAP server.
 * <p>
 * There are many ways in which an LDAP directory can be configured so this class
 * delegates most of its responsibilities to two separate strategy interfaces,
 * {@link LdapAuthenticator} and {@link LdapAuthoritiesPopulator}.
 *
 * <h3>LdapAuthenticator</h3> This interface is responsible for performing the user
 * authentication and retrieving the user's information from the directory. Example
 * implementations are
 * {@link org.springframework.security.ldap.authentication.BindAuthenticator
 * BindAuthenticator} which authenticates the user by "binding" as that user, and
 * {@link org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator
 * PasswordComparisonAuthenticator} which compares the supplied password with the value
 * stored in the directory, using an LDAP "compare" operation.
 * <p>
 * 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).
 *
 * <h3>LdapAuthoritiesPopulator</h3> Once the user has been authenticated, this interface
 * is called to obtain the set of granted authorities for the user. The
 * {@link 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.
 *
 * <p>
 * A custom implementation could obtain the roles from a completely different source, for
 * example from a database.
 *
 * <h3>Configuration</h3>
 *
 * A simple configuration might be as follows:
 *
 * <pre>
 *   &lt;bean id=&quot;contextSource&quot;
 *       class=&quot;org.springframework.security.ldap.DefaultSpringSecurityContextSource&quot;&gt;
 *     &lt;constructor-arg value=&quot;ldap://monkeymachine:389/dc=springframework,dc=org&quot;/&gt;
 *     &lt;property name=&quot;userDn&quot; value=&quot;cn=manager,dc=springframework,dc=org&quot;/&gt;
 *     &lt;property name=&quot;password&quot; value=&quot;password&quot;/&gt;
 *   &lt;/bean&gt;
 *
 *   &lt;bean id=&quot;ldapAuthProvider&quot;
 *       class=&quot;org.springframework.security.ldap.authentication.LdapAuthenticationProvider&quot;&gt;
 *     &lt;constructor-arg&gt;
 *       &lt;bean class=&quot;org.springframework.security.ldap.authentication.BindAuthenticator&quot;&gt;
 *           &lt;constructor-arg ref=&quot;contextSource&quot;/&gt;
 *           &lt;property name=&quot;userDnPatterns&quot;&gt;&lt;list&gt;&lt;value&gt;uid={0},ou=people&lt;/value&gt;&lt;/list&gt;&lt;/property&gt;
 *       &lt;/bean&gt;
 *     &lt;/constructor-arg&gt;
 *     &lt;constructor-arg&gt;
 *       &lt;bean class=&quot;org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator&quot;&gt;
 *           &lt;constructor-arg ref=&quot;contextSource&quot;/&gt;
 *           &lt;constructor-arg value=&quot;ou=groups&quot;/&gt;
 *           &lt;property name=&quot;groupRoleAttribute&quot; value=&quot;ou&quot;/&gt;
 *       &lt;/bean&gt;
 *     &lt;/constructor-arg&gt;
 *   &lt;/bean&gt;
 * </pre>
 *
 * <p>
 * This would set up the provider to access an LDAP server with URL
 * <tt>ldap://monkeymachine:389/dc=springframework,dc=org</tt>. Authentication will be
 * performed by attempting to bind with the DN
 * <tt>uid=&lt;user-login-name&gt;,ou=people,dc=springframework,dc=org</tt>. After
 * successful authentication, roles will be assigned to the user by searching under the DN
 * <tt>ou=groups,dc=springframework,dc=org</tt> with the default filter
 * <tt>(member=&lt;user's-DN&gt;)</tt>. The role name will be taken from the "ou"
 * attribute of each match.
 * <p>
 * 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 unauthenticated access, it
 * might be possible to authenticate as <i>any</i> user just by supplying an empty
 * password. More information on the misuse of unauthenticated access can be found in
 * <a href="https://www.ietf.org/internet-drafts/draft-ietf-ldapbis-authmeth-19.txt">
 * draft -ietf-ldapbis-authmeth-19.txt</a>.
 *
 * @author Luke Taylor
 * @see BindAuthenticator
 * @see DefaultLdapAuthoritiesPopulator
 */
public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvider {

	private LdapAuthenticator authenticator;

	private LdapAuthoritiesPopulator authoritiesPopulator;

	private boolean hideUserNotFoundExceptions = true;

	/**
	 * Create an instance with the supplied authenticator and authorities populator
	 * implementations.
	 * @param authenticator the authentication strategy (bind, password comparison, etc)
	 * to be used by this provider for authenticating users.
	 * @param authoritiesPopulator the strategy for obtaining the authorities for a given
	 * user after they've been authenticated.
	 */
	public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
		this.setAuthenticator(authenticator);
		this.setAuthoritiesPopulator(authoritiesPopulator);
	}

	/**
	 * Creates an instance with the supplied authenticator and a null authorities
	 * populator. In this case, the authorities must be mapped from the user context.
	 * @param authenticator the authenticator strategy.
	 */
	public LdapAuthenticationProvider(LdapAuthenticator authenticator) {
		this.setAuthenticator(authenticator);
		this.setAuthoritiesPopulator(new NullLdapAuthoritiesPopulator());
	}

	private void setAuthenticator(LdapAuthenticator authenticator) {
		Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
		this.authenticator = authenticator;
	}

	private LdapAuthenticator getAuthenticator() {
		return this.authenticator;
	}

	private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) {
		Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied");
		this.authoritiesPopulator = authoritiesPopulator;
	}

	protected LdapAuthoritiesPopulator getAuthoritiesPopulator() {
		return this.authoritiesPopulator;
	}

	public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) {
		this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
	}

	@Override
	protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken authentication) {
		try {
			return getAuthenticator().authenticate(authentication);
		}
		catch (PasswordPolicyException ex) {
			// The only reason a ppolicy exception can occur during a bind is that the
			// account is locked.
			throw new LockedException(
					this.messages.getMessage(ex.getStatus().getErrorCode(), ex.getStatus().getDefaultMessage()));
		}
		catch (UsernameNotFoundException ex) {
			if (this.hideUserNotFoundExceptions) {
				throw new BadCredentialsException(
						this.messages.getMessage("LdapAuthenticationProvider.badCredentials", "Bad credentials"));
			}
			throw ex;
		}
		catch (NamingException ex) {
			throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
		}
	}

	@Override
	protected Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username,
			String password) {
		return getAuthoritiesPopulator().getGrantedAuthorities(userData, username);
	}

}

相关信息

spring security 源码目录

相关文章

spring security AbstractLdapAuthenticationProvider 源码

spring security AbstractLdapAuthenticator 源码

spring security BindAuthenticator 源码

spring security LdapAuthenticator 源码

spring security LdapEncoder 源码

spring security NullLdapAuthoritiesPopulator 源码

spring security PasswordComparisonAuthenticator 源码

spring security SpringSecurityAuthenticationSource 源码

spring security UserDetailsServiceLdapAuthoritiesPopulator 源码

spring security package-info 源码

0  赞