| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
| BindAuthenticator |
|
| 2.75;2.75 |
| 1 | /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
|
| 2 | * |
|
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 | * you may not use this file except in compliance with the License. |
|
| 5 | * You may obtain a copy of the License at |
|
| 6 | * |
|
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 | * |
|
| 9 | * Unless required by applicable law or agreed to in writing, software |
|
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 | * See the License for the specific language governing permissions and |
|
| 13 | * limitations under the License. |
|
| 14 | */ |
|
| 15 | ||
| 16 | package org.acegisecurity.providers.ldap.authenticator; |
|
| 17 | ||
| 18 | import org.acegisecurity.BadCredentialsException; |
|
| 19 | ||
| 20 | import org.acegisecurity.ldap.InitialDirContextFactory; |
|
| 21 | import org.acegisecurity.ldap.LdapTemplate; |
|
| 22 | ||
| 23 | import org.acegisecurity.userdetails.ldap.LdapUserDetails; |
|
| 24 | import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; |
|
| 25 | ||
| 26 | import org.apache.commons.logging.Log; |
|
| 27 | import org.apache.commons.logging.LogFactory; |
|
| 28 | ||
| 29 | import java.util.Iterator; |
|
| 30 | ||
| 31 | ||
| 32 | /** |
|
| 33 | * An authenticator which binds as a user. |
|
| 34 | * |
|
| 35 | * @author Luke Taylor |
|
| 36 | * @version $Id: BindAuthenticator.java 2348 2007-12-07 16:04:43Z luke_t $ |
|
| 37 | * |
|
| 38 | * @see AbstractLdapAuthenticator |
|
| 39 | */ |
|
| 40 | public class BindAuthenticator extends AbstractLdapAuthenticator { |
|
| 41 | //~ Static fields/initializers ===================================================================================== |
|
| 42 | ||
| 43 | 2 | private static final Log logger = LogFactory.getLog(BindAuthenticator.class); |
| 44 | ||
| 45 | //~ Constructors =================================================================================================== |
|
| 46 | ||
| 47 | /** |
|
| 48 | * Create an initialized instance to the {@link InitialDirContextFactory} provided. |
|
| 49 | * |
|
| 50 | * @param initialDirContextFactory |
|
| 51 | */ |
|
| 52 | public BindAuthenticator(InitialDirContextFactory initialDirContextFactory) { |
|
| 53 | 6 | super(initialDirContextFactory); |
| 54 | 6 | } |
| 55 | ||
| 56 | //~ Methods ======================================================================================================== |
|
| 57 | ||
| 58 | public LdapUserDetails authenticate(String username, String password) { |
|
| 59 | 5 | LdapUserDetails user = null; |
| 60 | ||
| 61 | // If DN patterns are configured, try authenticating with them directly |
|
| 62 | 5 | Iterator dns = getUserDns(username).iterator(); |
| 63 | ||
| 64 | 9 | while (dns.hasNext() && (user == null)) { |
| 65 | 4 | user = bindWithDn((String) dns.next(), username, password); |
| 66 | } |
|
| 67 | ||
| 68 | // Otherwise use the configured locator to find the user |
|
| 69 | // and authenticate with the returned DN. |
|
| 70 | 5 | if ((user == null) && (getUserSearch() != null)) { |
| 71 | 1 | LdapUserDetails userFromSearch = getUserSearch().searchForUser(username); |
| 72 | 1 | user = bindWithDn(userFromSearch.getDn(), username, password); |
| 73 | } |
|
| 74 | ||
| 75 | 5 | if (user == null) { |
| 76 | 2 | throw new BadCredentialsException( |
| 77 | messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); |
|
| 78 | } |
|
| 79 | ||
| 80 | 3 | return user; |
| 81 | } |
|
| 82 | ||
| 83 | private LdapUserDetails bindWithDn(String userDn, String username, String password) { |
|
| 84 | 5 | LdapTemplate template = new LdapTemplate(getInitialDirContextFactory(), userDn, password); |
| 85 | ||
| 86 | try { |
|
| 87 | 5 | LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.retrieveEntry(userDn, |
| 88 | getUserDetailsMapper(), getUserAttributes()); |
|
| 89 | 3 | user.setUsername(username); |
| 90 | 3 | user.setPassword(password); |
| 91 | ||
| 92 | 3 | return user.createUserDetails(); |
| 93 | 2 | } catch (BadCredentialsException e) { |
| 94 | // This will be thrown if an invalid user name is used and the method may |
|
| 95 | // be called multiple times to try different names, so we trap the exception |
|
| 96 | // unless a subclass wishes to implement more specialized behaviour. |
|
| 97 | 2 | handleBindException(userDn, username, e.getCause()); |
| 98 | } |
|
| 99 | ||
| 100 | 2 | return null; |
| 101 | } |
|
| 102 | ||
| 103 | /** |
|
| 104 | * Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN. |
|
| 105 | * The default implementation just reports the failure to the debug log. |
|
| 106 | */ |
|
| 107 | void handleBindException(String userDn, String username, Throwable cause) { |
|
| 108 | 2 | if (logger.isDebugEnabled()) { |
| 109 | 0 | logger.debug("Failed to bind as " + userDn + ": " + cause); |
| 110 | } |
|
| 111 | 2 | } |
| 112 | } |