A whole bunch of changes to the LDAP Authentication process. It should be both more object oriented, and faster.

[Note] I am checking this in in advance of having time to actually test it.
[Note] This class will probably be renamed to replace the current LdapPasswordAuthenticationDao .
This commit is contained in:
Robert Sanders 2005-06-07 02:44:58 +00:00
parent 645c2bb5d5
commit a163fc48ef
1 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,177 @@
/**
*
*/
package net.sf.acegisecurity.providers.dao.ldap;
import java.util.ArrayList;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import net.sf.acegisecurity.providers.dao.User;
import net.sf.acegisecurity.BadCredentialsException;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.PasswordAuthenticationDao;
/**
* Re-written version of the ACEGI LDAP code,
* designed to be cleaner; it is partially based on
* the description of the mod_auth_ldap logic: http://httpd.apache.org/docs-2.0/mod/mod_auth_ldap.html
*
*
*
*/
public class LdapPassword2AuthenticationDao implements PasswordAuthenticationDao {
public static final String BAD_CREDENTIALS_EXCEPTION_MESSAGE = "Invalid username, password or context";
private static final transient Log logger = LogFactory.getLog(LdapPassword2AuthenticationDao.class);
/** Ldap base settings. */
private LdapSupport ldapSupport;
/** Array of LdapSearchBean which will be used to search the context.
*/
private UserSearchBean[] ldapSearchBeans;
private String defaultRole;
public UserDetails loadUserByUsernameAndPassword(String username, String password) throws DataAccessException, BadCredentialsException {
if ((password == null) || (password.length() == 0)) {
throw new BadCredentialsException("Empty password");
}
UserSearchResults userSearchResults = getUserBySearch(username);
if (null == userSearchResults) {
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
}
DirContext userDirContext = null;
try {
userDirContext = loginToUserDirContext( userSearchResults.getUserLoginName(), password );
if (null == userDirContext) {
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
}
String[] roleAttrs = userSearchResults.getUserSearchBean().getRoleAttributes();
GrantedAuthority[] roles = getUserRolesLdap(userDirContext, roleAttrs);
if ((roles == null) && (null != defaultRole)) {
roles = new GrantedAuthority[] { new GrantedAuthorityImpl(defaultRole) };
}
if (null != roles) {
return new User( userSearchResults.getUserLoginName(),
password,
true,
true,
true,
true,
roles);
} else {
logger.info("User was able to login, but had no role information; username = [" + username + "]");
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
}
} finally {
try {
if (null != userDirContext) {
userDirContext.close();
}
} catch (NamingException e) {
logger.warn("Unable to properly close userDirContext.", e);
}
}
}
protected UserSearchResults getUserBySearch(String username) throws DataAccessException, BadCredentialsException {
InitialDirContext ctx = ldapSupport.getInitialContext();
UserSearchResults userSearchResults = null;
try {
for (int i = 0; (i < ldapSearchBeans.length) && (null == userSearchResults); i++) {
try {
userSearchResults = ldapSearchBeans[i].searchForUser(ctx, username);
} catch (NamingException nx) {
logger.warn(nx);
}
}
} finally {
try {
ctx.close();
} catch (NamingException e) {
logger.warn("Unable to properly close JNDI LDAP connection.", e);
}
}
return userSearchResults;
}
protected DirContext loginToUserDirContext(String username, String password) {
Hashtable baseEnv = ldapSupport.getEnvironment();
baseEnv.put(Context.SECURITY_PRINCIPAL, username);
baseEnv.put(Context.SECURITY_CREDENTIALS, password);
try {
return new InitialDirContext(baseEnv);
} catch (NamingException e) {
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE, e);
}
}
protected GrantedAuthority[] getUserRolesLdap(DirContext ctx, String[] roleAttrs) {
try {
NamingEnumeration enm = ctx.search((Name)null, null, roleAttrs, null);
if (!enm.hasMore()) {
return null;
}
// LDAP Search result which SHOULD contain the user's roles
SearchResult searchResult = (SearchResult)enm.next();
Attributes attrs = searchResult.getAttributes();
ArrayList roleList = new ArrayList(attrs.size());
NamingEnumeration attrEnm = attrs.getAll();
while (attrEnm.hasMore()) {
Attribute attr = (Attribute)attrEnm.next();
for (int i = 0; i < attr.size(); i++) {
roleList.add( new GrantedAuthorityImpl((String)attr.get(i)) );
}
}
GrantedAuthorityImpl[] roles = new GrantedAuthorityImpl[ roleList.size() ];
return (GrantedAuthorityImpl[])roleList.toArray(roles);
} catch (NamingException e) {
// TODO Convert to authentication exception
e.printStackTrace();
}
return null;
}
/**
* @return Returns the defaultRole.
*/
public String getDefaultRole() {
return defaultRole;
}
/**
* @param defaultRole The defaultRole to set.
*/
public void setDefaultRole(String defaultRole) {
this.defaultRole = defaultRole;
}
}