LDAPUtils.java:
package app;I'm then extending SwingX's LoginService to work with this class and return some extra details, like the user's group (this can be easily expanded to capture an Active Directory attribute):
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
/*
@author Randy Coates
Modified slightly by Dave Gruska
*/
public class LDAPUtils {
static String ATTRIBUTE_FOR_USER = "sAMAccountName";
public Attributes authenticateUser(String username, String password, String _domain, String host, String dn) {
String returnedAtts[] ={ "sAMAccountName", "memberOf" };
String searchFilter = "(&(objectClass=user)(" + ATTRIBUTE_FOR_USER + "=" + username + "))";
//Create the search controls
SearchControls searchCtls = new SearchControls();
searchCtls.setReturningAttributes(returnedAtts);
//Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//Using starndard Port, check your instalation
environment.put(Context.PROVIDER_URL, "ldap://" + host + ":389");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, username + "@" + _domain);
environment.put(Context.SECURITY_CREDENTIALS, password);
LdapContext ctxGC = null;
try {
ctxGC = new InitialLdapContext(environment, null);
//search for objects in the GC using the filter
String searchBase = dn;
NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult)answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null)
return attrs;
}
}
catch (NamingException e) {
e.printStackTrace();
}
return null;
}
}
LDAPLoginService:
package app;and finally, the presentation layer code displays a login pane (JXLoginPane dialog) that gets called in the constructor right after the components are initialized:
import javax.naming.directory.Attributes;
import org.jdesktop.swingx.auth.LoginService;
/*
@author Dave Gruska
*/
public class LDAPLoginService extends LoginService {
private String domain;
private String host;
private String dn;
private String userName;
private String groupName;
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getDn() {
return dn;
}
public void setDn(String dn) {
this.dn = dn;
}
public String getUserName() {
return userName;
}
public String getGroupName() {
return groupName;
}
public LDAPLoginService(String domain, String host, String dn) {
this.domain = domain;
this.host = host;
this.dn = dn;
}
@Override
public boolean authenticate(String name, char[] password, String server) throws Exception {
LDAPUtils LDAPlogin = new LDAPUtils();
//TODO: investigate if there's a more efficient way to convert this
StringBuilder passwd = new StringBuilder();
for(char c : password) {
passwd.append(c);
}
Attributes attrs = LDAPlogin.authenticateUser(name, passwd.toString(), this.domain, this.host, this.dn);
if(attrs == null) {
//login failed
return false;
} else {
//login successful
String[] splitUserName = attrs.get("sAMAccountName").toString().split(":");
userName = splitUserName[1].trim();
groupName = attrs.get("memberOf").contains("CN=AppAdmins,CN=Users,DC=domain,DC=com") ? "admin" : "user";
return true;
}
}
}
loginService = new LDAPLoginService("domain.com", "[domain controller IP]", "cn=Users,dc=domain,dc=com");BTW, the System.exit code only gets called when the user gives up on trying to log in.
JXLoginPane.Status status = JXLoginPane.showLoginDialog(null, loginService);
if(!status.equals(status.SUCCEEDED)) {
System.exit(0);
}
loggedInAsLabel.setText(String.format("%S (%s)", loginService.getUserName(), loginService.getGroupName()));