The Microsoft implementation of the LDAP interface is limited to 1000 query results. So to handle more than 1000 results, we have to maintain a cookie that stores the current position of retrieved results and pass the cookie back to the server to continue the query from the cookie stored position. This is called a paged query.
We first start by creating a LdapContext object, which we'll use to access Active Directory through the LDAP interface. The Context object is configured using a Hashtable.
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "<user>");
env.put(Context.SECURITY_CREDENTIALS, "<password>");
env.put(Context.PROVIDER_URL, "ldap://<host>:389");
env.put(Context.REFERRAL, "follow");
// We want to use a connection pool to
// improve connection reuse and performance.
env.put("com.sun.jndi.ldap.connect.pool", "true");
// The maximum time in milliseconds we are going
// to wait for a pooled connection.
env.put("com.sun.jndi.ldap.connect.timeout", "300000");
Next, we need to specify how we are going to search the directory with a SearchControls object, from where we want to start the search with a search base string, and how we want to filter results.
SearchControls searchCtls = new SearchControls();
// We start our search from the search base.
// Be careful! The string needs to be escaped!
String searchBase = "dc=company,dc=com";
// There are different search scopes:
// - OBJECT_SCOPE, to search the named object
// - ONELEVEL_SCOPE, to search in only one level of the tree
// - SUBTREE_SCOPE, to search the entire subtree
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// We only want groups, so we filter the search for
// objectClass=group. We use wildcards to find all groups with the
// string "<group>" in its name. If we want to find users, we can
// use: "(&(objectClass=person)(cn=*<username>*))".
String searchFilter = "(&(objectClass=group)(cn=*<group>*))";
// We want all results.
searchCtls.setCountLimit(0);
// We want to wait to get all results.
searchCtls.setTimeLimit(0);
// Active Directory limits our results, so we need multiple
// requests to retrieve all results. The cookie is used to
// save the current position.
byte[] cookie = null;
// We want 500 results per request.
ctx.setRequestControls(
new Control[] {
new PagedResultsControl(500, Control.CRITICAL)
});
// We only want to retrieve the "distinguishedName" attribute.
// You can specify other attributes/properties if you want here.
String returnedAtts[] = { "distinguishedName" };
searchCtls.setReturningAttributes(returnedAtts);
// The request loop starts here.
do {
// Start the search with our configuration.
NamingEnumeration<SearchResult> answer = ctx.search(
searchBase, searchFilter, searchCtls);
// Loop through the search results.
while (answer.hasMoreElements()) {
SearchResult sr = answer.next();
Attributes attr = sr.getAttributes();
Attribute a = attr.get("distinguishedName");
// Print our wanted attribute value.
System.out.println((String) a.get());
}
// Find the cookie in our response and save it.
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof
PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) controls[i];
cookie = prrc.getCookie();
}
}
}
// Use the cookie to configure our new request
// to start from the saved position in the cookie.
ctx.setRequestControls(new Control[] {
new PagedResultsControl(500,
cookie,
Control.CRITICAL) });
} while (cookie != null);
// We are done, so close the Context object.
ctx.close();
We can also print all attributes from an object using its fully distinguished name using the following code:
String dN = "CN=JohnDoe,OU=Users,DC=company,DC=com";
Attributes answer = ctx.getAttributes(dN);
for (NamingEnumeration<?> ae = answer.getAll(); ae.hasMore();) {
Attribute attr = (Attribute) ae.next();
String attributeName = attr.getID();
for (NamingEnumeration<?> e = attr.getAll(); e.hasMore();) {
System.out.println(attributeName + "=" + e.next());
}
}
No comments:
Post a Comment