package com.hwlcn.security.realm.activedirectory;
import com.hwlcn.security.authc.AuthenticationInfo;
import com.hwlcn.security.authc.AuthenticationToken;
import com.hwlcn.security.authc.SimpleAuthenticationInfo;
import com.hwlcn.security.authc.UsernamePasswordToken;
import com.hwlcn.security.authz.AuthorizationInfo;
import com.hwlcn.security.authz.SimpleAuthorizationInfo;
import com.hwlcn.security.realm.ldap.AbstractLdapRealm;
import com.hwlcn.security.realm.ldap.LdapUtils;
import com.hwlcn.security.subject.PrincipalCollection;
import com.hwlcn.security.realm.ldap.LdapContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;
import java.util.*;
public class ActiveDirectoryRealm extends AbstractLdapRealm {
private static final Logger log = LoggerFactory.getLogger(ActiveDirectoryRealm.class);
private static final String ROLE_NAMES_DELIMETER = ",";
private Map<String, String> groupRolesMap;
public void setGroupRolesMap(Map<String, String> groupRolesMap) {
this.groupRolesMap = groupRolesMap;
}
protected AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token, LdapContextFactory ldapContextFactory) throws NamingException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
LdapContext ctx = null;
try {
ctx = ldapContextFactory.getLdapContext(upToken.getUsername(), String.valueOf(upToken.getPassword()));
} finally {
LdapUtils.closeContext(ctx);
}
return buildAuthenticationInfo(upToken.getUsername(), upToken.getPassword());
}
protected AuthenticationInfo buildAuthenticationInfo(String username, char[] password) {
return new SimpleAuthenticationInfo(username, password, getName());
}
protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals, LdapContextFactory ldapContextFactory) throws NamingException {
String username = (String) getAvailablePrincipal(principals);
LdapContext ldapContext = ldapContextFactory.getSystemLdapContext();
Set<String> roleNames;
try {
roleNames = getRoleNamesForUser(username, ldapContext);
} finally {
LdapUtils.closeContext(ldapContext);
}
return buildAuthorizationInfo(roleNames);
}
protected AuthorizationInfo buildAuthorizationInfo(Set<String> roleNames) {
return new SimpleAuthorizationInfo(roleNames);
}
private Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
Set<String> roleNames;
roleNames = new LinkedHashSet<String>();
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String userPrincipalName = username;
if (principalSuffix != null) {
userPrincipalName += principalSuffix;
}
String searchFilter = "(&(objectClass=*)(userPrincipalName={0}))";
Object[] searchArguments = new Object[]{userPrincipalName};
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
if (log.isDebugEnabled()) {
log.debug("Retrieving group names for user [" + sr.getName() + "]");
}
Attributes attrs = sr.getAttributes();
if (attrs != null) {
NamingEnumeration ae = attrs.getAll();
while (ae.hasMore()) {
Attribute attr = (Attribute) ae.next();
if (attr.getID().equals("memberOf")) {
Collection<String> groupNames = LdapUtils.getAllAttributeValues(attr);
if (log.isDebugEnabled()) {
log.debug("Groups found for user [" + username + "]: " + groupNames);
}
Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
roleNames.addAll(rolesForGroups);
}
}
}
}
return roleNames;
}
protected Collection<String> getRoleNamesForGroups(Collection<String> groupNames) {
Set<String> roleNames = new HashSet<String>(groupNames.size());
if (groupRolesMap != null) {
for (String groupName : groupNames) {
String strRoleNames = groupRolesMap.get(groupName);
if (strRoleNames != null) {
for (String roleName : strRoleNames.split(ROLE_NAMES_DELIMETER)) {
if (log.isDebugEnabled()) {
log.debug("User is member of group [" + groupName + "] so adding role [" + roleName + "]");
}
roleNames.add(roleName);
}
}
}
}
return roleNames;
}
}