Sample Java application that retrieves group membership of an Active Directory user account.
This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm
This is a sample Java application that utilizes JNDI to access Active Directory and retrieves group membership of a user. This application uses computed tokenGroups attribute of a user object in order to get complete list of groups a user belongs to, including membership acquired through nested groups and built-in groups (ex. Domain Users).
Credits
There is almost no my code in this sample. I constructed this application by pulling together snippets from various posts on the Naming and Directory (JNDI) Forum , but since it took me a while to pull this all together I think there may be a value of having such useful sample all in one place.
Specifically I used the post (see link below) by Steven Adler. Steven also provided me with a function to convert binary value of a SID into its string representation. I needed this function since tokenGroups stores group SIDs in binary format.
https://forum.java.sun.com/thread.jspa?threadID=581444&tstart=150
package adconnection;
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.ldap.*;
import javax.naming.directory.*;
public class memberof {
public static void main (String[] args) {
Hashtable env = new Hashtable();
String adminName = "CN=Administrator,CN=Users,DC=ADATUM,DC=COM";
String adminPassword = "XXXXXXXXXXX";
String ldapURL = "ldap://adfsaccount.adatum.com:389";
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
//set security credentials, note using simple cleartext authentication
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.SECURITY_PRINCIPAL,adminName);
env.put(Context.SECURITY_CREDENTIALS,adminPassword);
//connect to my domain controller
env.put(Context.PROVIDER_URL,ldapURL);
//specify attributes to be returned in binary format
env.put("java.naming.ldap.attributes.binary","tokenGroups");
try {
//Create the initial directory context
LdapContext ctx = new InitialLdapContext(env,null);
//Create the search controls
SearchControls userSearchCtls = new SearchControls();
//Specify the search scope
userSearchCtls.setSearchScope(SearchControls.OBJECT_SCOPE);
//specify the LDAP search filter to find the user in question
String userSearchFilter = "(objectClass=user)";
//paceholder for an LDAP filter that will store SIDs of the groups the user belongs to
StringBuffer groupsSearchFilter = new StringBuffer();
groupsSearchFilter.append("(|");
//Specify the Base for the search
String userSearchBase = "CN=Alex Tcherni,CN=Users,DC=adatum,DC=com";
//Specify the attributes to return
String userReturnedAtts[]={"tokenGroups"};
userSearchCtls.setReturningAttributes(userReturnedAtts);
//Search for objects using the filter
NamingEnumeration userAnswer = ctx.search(userSearchBase, userSearchFilter, userSearchCtls);
//Loop through the search results
while (userAnswer.hasMoreElements()) {
SearchResult sr = (SearchResult)userAnswer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
try {
for (NamingEnumeration ae = attrs.getAll();ae.hasMore();) {
Attribute attr = (Attribute)ae.next();
for (NamingEnumeration e = attr.getAll();e.hasMore();) {
byte[] sid = (byte[])e.next();
groupsSearchFilter.append("(objectSid=" + binarySidToStringSid(sid) + ")");
}
groupsSearchFilter.append(")");
}
}
catch (NamingException e) {
System.err.println("Problem listing membership: " + e);
}
}
}
// Search for groups the user belongs to in order to get their names
//Create the search controls
SearchControls groupsSearchCtls = new SearchControls();
//Specify the search scope
groupsSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//Specify the Base for the search
String groupsSearchBase = "DC=adatum,DC=com";
//Specify the attributes to return
String groupsReturnedAtts[]={"sAMAccountName"};
groupsSearchCtls.setReturningAttributes(groupsReturnedAtts);
//Search for objects using the filter
NamingEnumeration groupsAnswer = ctx.search(groupsSearchBase, groupsSearchFilter.toString(), groupsSearchCtls);
//Loop through the search results
while (groupsAnswer.hasMoreElements()) {
SearchResult sr = (SearchResult)groupsAnswer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
System.out.println(attrs.get("sAMAccountName").get());
}
}
ctx.close();
}
catch (NamingException e) {
System.err.println("Problem searching directory: " + e);
}
}
public static final String binarySidToStringSid( byte[] SID ) {
String strSID = "";
//convert the SID into string format
long version;
long authority;
long count;
long rid;
strSID = "S";
version = SID[0];
strSID = strSID + "-" + Long.toString(version);
authority = SID[4];
for (int i = 0;i<4;i++) {
authority <<= 8;
authority += SID[4+i] & 0xFF;
}
strSID = strSID + "-" + Long.toString(authority);
count = SID[2];
count <<= 8;
count += SID[1] & 0xFF;
for (int j=0;j<count;j++) {
rid = SID[11 + (j*4)] & 0xFF;
for (int k=1;k<4;k++) {
rid <<= 8;
rid += SID[11-k + (j*4)] & 0xFF;
}
strSID = strSID + "-" + Long.toString(rid);
}
return strSID;
}
}
Comments
- Anonymous
June 18, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/06/18/ - Anonymous
October 21, 2008
Since users are automatically added to Domain Users, it would be nice if this group could be used by Crowdified applications like JIRA or Confluence. Articles of Interest: http://blogs.msdn.com/alextch/archive/2007/06/18/sample-java-applicatio...