ldap search is very slow

14,055

Solution 1

Solution was to change ldapEnv.put(Context.REFERRAL, "follow"); to ldapEnv.put(Context.REFERRAL, "ignore");

Solution 2

Your filter:

"(&(ObjectCategory=person)(cn=*" + name + "*))"

May be an issue.

I would recommend that you download a known LDAP utility (Apache Directory Studio Browser as an example) and try different search filters until you find one that works.

To Start, try

"(&(ObjectCategory=person)(cn= + name ))"

Solution 3

You're right,

ldapEnv.put(Context.REFERRAL, "ignore") 

didn't get exception about connection timed out. But when I first try I get a partialexception. After I changed my LDAP configuration port from 389 to 3268 I didn't get any exception, build successfully. 3268 port about global catalog of LDAP. For example Outlook clients query the global catalog to locate Address Book information. You can try global catalog if you get an exception referral type setting.

Share:
14,055
Mahmoud Saleh
Author by

Mahmoud Saleh

I am Mahmoud Saleh an Enthusiastic Software Engineer, Computer Science Graduate, Experienced in developing J2EE applications, Currently developing with Spring,JSF,Primefaces,Hibernate,Filenet. Email: [email protected] Linkedin: https://www.linkedin.com/in/mahmoud-saleh-60465545? Upwork: http://www.upwork.com/o/profiles/users/_~012a6a88e04dd2c1ed/

Updated on July 06, 2022

Comments

  • Mahmoud Saleh
    Mahmoud Saleh almost 2 years

    I am using JNDI to connect to the LDAP active directory, and I want to search for users where the name contains the search string, so my search method is as follows:

    public static List<LDAPUser> searchContactsByName(
            ExtendedDirContext extendedDirContext, String name) {
    
        try {
    
            LdapContext ldapContext = extendedDirContext.getLdapContext();
            String searchBaseStr = extendedDirContext.getSearchBase();
    
            String sortKey = LDAPAttributes.NAME;
            ldapContext.setRequestControls(new Control[] { new SortControl(
                    sortKey, Control.CRITICAL) });
    
            SearchControls searchCtls = new SearchControls();
            searchCtls.setTimeLimit(1000 * 10);
    
            String returnedAtts[] = { LDAPAttributes.USER_NAME,
                    LDAPAttributes.NAME };
            searchCtls.setReturningAttributes(returnedAtts);
    
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    
            String searchFilter = "(&(ObjectCategory=person)(cn=*" + name
                    + "*))";
    
            NamingEnumeration<SearchResult> results = ldapContext.search(
                    searchBaseStr, searchFilter, searchCtls);
    
            List<LDAPUser> users = new ArrayList<LDAPUser>(0);
            while (results.hasMoreElements()) {
                SearchResult sr = (SearchResult) results.next();
                Attributes attrs = sr.getAttributes();
                LDAPUser user = new LDAPUser();
                user.setName(attrs.get(LDAPAttributes.NAME).toString()
                        .replace("cn: ", ""));
                user.setUserName(attrs.get(LDAPAttributes.USER_NAME).toString()
                        .replace("sAMAccountName: ", ""));
                users.add(user);
            }
    
            return users;
    
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    

    and here is how I am making the connection to LDAP:

    public static ExtendedDirContext connectToLdap(MessageSource messageSource) {
    
        try {
            log.debug("connectToLdap");
            String providerUrl = messageSource.getMessage("provider.url", null,
                    null);
            String securityPrincipal = messageSource.getMessage(
                    "security.principal", null, null);
            String securityCredentials = messageSource.getMessage(
                    "security.credentials", null, null);
            String searchBase = messageSource.getMessage("search.base", null,
                    null);
            boolean ssl = Boolean.parseBoolean(messageSource.getMessage("ssl",
                    null, null));
            LdapContext ldapContext;
    
            Hashtable<String, String> ldapEnv = new Hashtable<String, String>(
                    11);
            ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
                    "com.sun.jndi.ldap.LdapCtxFactory");
            ldapEnv.put(Context.PROVIDER_URL, providerUrl);
            ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
            ldapEnv.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
            ldapEnv.put(Context.SECURITY_CREDENTIALS, securityCredentials);
            if (ssl)
                ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
            // To get rid of the PartialResultException when using Active
            // Directory
            ldapEnv.put(Context.REFERRAL, "follow");
            ldapContext = new InitialLdapContext(ldapEnv, null);
            ExtendedDirContext extendedDirContext = new ExtendedDirContext();
            extendedDirContext.setLdapContext(ldapContext);
            extendedDirContext.setSearchBase(searchBase);
            log.debug("success connection to ldap");
            return extendedDirContext;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    
    }
    

    The LDAP credentials are as follows:

    provider.url=ldap://dc.fabrikam.com:389
    security.principal=CN=administrator,CN=Users,DC=fabrikam,DC=com
    security.credentials=password
    search.base=dc=fabrikam,dc=com
    

    Why does the search take so much time to retrieve the data? Is there any change that I can do to make the search faster, since I have only 285 contacts in the AD?

  • Nicholas DiPiazza
    Nicholas DiPiazza over 7 years
    yes that as my explanation as well. weird! and thank you