sergiopf
sergiopf

Reputation: 61

Retrieve more than 1000 records in LDAP using springboot

I'm using ldaptemplate to retrieve many records from Active Directory using sring-ldap-core 3.2. This is the code I'm using

    AndFilter filter = new AndFilter();
    filter.and(new EqualsFilter("employeeType", "PROGRAMMER"));

    List<String> results = new ArrayList<>();
    byte[] cookie = null; // Initialize cookie to null

    do {
        // Create a new LDAP context for each page of results
        LdapContext ldapContext = (LdapContext) ldapTemplate.getContextSource().getReadOnlyContext();
        ldapContext.setRequestControls(new Control[] { new PagedResultsControl(1000, cookie, Control.CRITICAL) });

        // Perform the search with pagination
        ldapTemplate.search("", filter.encode(), new AbstractContextMapper<String>() {
        @Override
        protected String doMapFromContext(DirContextOperations ctx) {
            return ctx.getNameInNamespace();
        }
        }).forEach(results::add);

        // After performing the search, check the response control for the cookie
        Control[] controls = ldapContext.getResponseControls();
        if (controls != null) {
        for (Control control : controls) {
            if (control instanceof PagedResultsResponseControl) {
            cookie = ((PagedResultsResponseControl) control).getCookie();
            }
        }
        }
        ldapContext.close();
} while (cookie != null && cookie.length > 0);

But the cookie to control pagination is always null, in fact ldapContext.getResponseControls() is always null so the pagination just returns the first query with 1000 records (the result should be much more records). I have disabled pooling in the ldap configuration because it's a recommendation but it doesn't work.

@Bean
public LdapContextSource ldapContextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(env.getRequiredProperty("ldap.urls"));
contextSource.setBase(env.getRequiredProperty("ldap.base"));
contextSource.setUserDn(env.getRequiredProperty("ldap.username"));
contextSource.setPassword(env.getRequiredProperty("ldap.password"));
contextSource.setPooled(false);
return contextSource;
}

I'm using Microsoft Active Directory and i don't know what else to try. Mostly i'll need smaller results (and i'll filter by modification date), but for strange cases i´ll need a lot of records to verify their state.

Upvotes: 0

Views: 38

Answers (1)

sergiopf
sergiopf

Reputation: 61

This worked:

AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("employeeType","PROGRAMMER"));

List<String> results = new ArrayList<>();
PagedResultsCookie cookie = null;
boolean hashMore = false;
do {
    Name baseDn = new LdapName("");
    SearchControls searchControls = new SearchControls();
    searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(1000, cookie);
    ldapTemplate.search(baseDn, filter.encode(), searchControls, (AttributesMapper<Void>) attrs -> {
    results.add(attrs.get("displayName").get().toString());
    return null;
    }, processor);

    System.out.println("size: " + results.size());
    cookie = processor.getCookie();
    hashMore = processor.hasMore();
} while (hashMore);

return results;

Upvotes: 0

Related Questions