it's me again. Unfortunately I didn't find the answer for this specific issue I'm having. Let me explain what I'm trying to do.
I'm developing a small system to control the computer labs at the University I work and study at. The users will use their domain user to log in to system. The integration itself is working, I'm already able to retrieve some info on the user, such as the groups they're part of, their name and other things (more info on the code below). But what I want to do exactly is something like Dell's SonicWall does. The user uses his AD account to access SonicWall, and the groups they're part of gives them access to certain websites.
I want to control access level through AD groups as well, and for such I need to retrieve only certain groups for the system to verify the permissions the user should have.
This is a brief on the system. And that is what I'm trying to do: use AD groups to give users certain permissions, but I'm not being able to retrieve only groups that start with labinfo_
. Below, the codes I have so far.
My main class, the one I'm using make tests.
import java.io.*;
import java.util.*;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchResult;
public class ActiveDirectoryTest {
public static void main(String[] args) throws NamingException, IOException {
try {
String domain = "umc.br";
String ch = "username";
String user, pwd, search;
Console console = System.console();
Scanner scan = new Scanner(System.in);
System.out.print("Usuário: ");
user = scan.next();
pwd = String.valueOf(console.readPassword("Senha: "));
System.out.print("Termo de busca: ");
search = scan.next();
ActiveDirectory activeDirectory = new ActiveDirectory(user, pwd, domain);
NamingEnumeration<SearchResult> result = activeDirectory.searchUser(search, ch, null);
if (result.hasMore()) {
SearchResult rs = (SearchResult) result.next();
Attributes attrs = rs.getAttributes();
String cn = attrs.get("cn").toString();
System.out.println("Nome completo: " + cn.substring(cn.indexOf(":") + 1));
String samaccountname = attrs.get("samaccountname").toString();
System.out.println("Usuário: " + samaccountname.substring(samaccountname.indexOf(":") + 1));
String groups = attrs.get("memberOf").toString();
System.out.println("Grupo: " + groups);
if (attrs.get("mail") == null) {
System.out.println("Email: não cadastrado");
} else {
String mail = attrs.get("mail").toString();
System.out.println("Email: " + mail.substring(mail.indexOf(":") + 1));
}
} else {
System.out.println("Resultado não encontrado!");
}
activeDirectory.closeLdapConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}
An ActiveDirectory class I found on the internet, with pre-made methods that give me info on the users.
import java.util.Properties;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
public class ActiveDirectory {
private static final Logger LOG = Logger.getLogger(ActiveDirectory.class.getName());
private Properties properties;
private DirContext dirContext;
private SearchControls searchCtls;
private String[] returnAttributes = {"sAMAccountName", "givenName", "cn", "mail", "memberOf"};
private String domainBase;
private String baseFilter = "(&((&(objectCategory=Person)(objectClass=User)))";
public ActiveDirectory(String username, String password, String domainController) {
properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.put(Context.PROVIDER_URL, "LDAP://" + domainController);
properties.put(Context.SECURITY_PRINCIPAL, username + "@" + domainController);
properties.put(Context.SECURITY_CREDENTIALS, password);
try {
dirContext = new InitialDirContext(properties);
} catch (NamingException e) {
LOG.severe(e.getMessage());
}
domainBase = getDomainBase(domainController);
searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchCtls.setReturningAttributes(returnAttributes);
}
public NamingEnumeration<SearchResult> searchUser(String searchValue, String searchBy, String searchBase) throws NamingException {
String filter = getFilter(searchValue, searchBy);
String base = (null == searchBase) ? domainBase : getDomainBase(searchBase);
return this.dirContext.search(base, filter, this.searchCtls);
}
public void closeLdapConnection() {
try {
if (dirContext != null) {
dirContext.close();
}
} catch (NamingException e) {
LOG.severe(e.getMessage());
}
}
private String getFilter(String searchValue, String searchBy) {
String filter = this.baseFilter;
if (searchBy.equals("email")) {
filter += "(mail=" + searchValue + "))";
} else if (searchBy.equals("username")) {
filter += "(samaccountname=" + searchValue + "))";
}
return filter;
}
private static String getDomainBase(String base) {
char[] namePair = base.toUpperCase().toCharArray();
String dn = "DC=";
for (int i = 0; i < namePair.length; i++) {
if (namePair[i] == '.') {
dn += ",DC=" + namePair[++i];
} else {
dn += namePair[i];
}
}
return dn;
}
}
EDIT: I changed the LDAP query to see if that would work. Well, the exception changed, haha. Now it gives me javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'DC=UMC,DC=BR'
.
The current LDAP query is (&((&(objectClass=group)(name=labinfo_*))&(objectCategory=Person)(objectClass=User))(samaccountname=" + searchValue + "))
.
EDIT2: I now changed the LDAP query to (&(&(objectCategory=person)(objectClass=user))(&(objectCategory=group)(sAMAccountName=labinfo_*))(sAMAccountName=" + searchValue + "))
, but I keep getting the same error.
I managed to return only the groups I wanted by using the query (&(objectClass=user)(memberOf=CN=" + group + ",OU=FIFTH_OU,OU=FOURTH_OU,OU=THIRD_OU,OU=SECOND,OU=FIRST_OU,DC=umc,DC=br)(sAMAccountName=" + searchValue + "))"
. I had to provide the whole path for the group, including all the OUs and DCs. It got me troubled for a long time, but it finally work.