Browse Source
[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 .1.0.x
1 changed files with 177 additions and 0 deletions
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue