ldap搜索非常慢

时间:2013-01-03 09:28:57

标签: java active-directory ldap jndi

我正在使用JNDI连接到LDAP活动目录,我想搜索名称中包含搜索字符串的用户,所以我的搜索方法如下:

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;
    }
}

以下是我与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;
    }

}

LDAP凭据如下:

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

为什么搜索需要花费大量时间来检索数据?我可以做些什么改变来加快搜索速度,因为我在AD中只有285个联系人?

3 个答案:

答案 0 :(得分:11)

解决方案是将ldapEnv.put(Context.REFERRAL, "follow");更改为ldapEnv.put(Context.REFERRAL, "ignore");

答案 1 :(得分:2)

您的过滤器:

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

可能是一个问题。

我建议您下载一个已知的LDAP实用程序(以Apache Directory Studio浏览器为例)并尝试使用不同的搜索过滤器,直到找到有效的搜索过滤器。

要开始,请尝试

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

答案 2 :(得分:1)

你是对的,

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

没有关于连接超时的异常。但是,当我第一次尝试时,我得到了一个偏爱。我将LDAP配置端口从389更改为3268后,我没有得到任何异常,构建成功。关于LDAP的全局目录的3268端口。例如,Outlook客户端查询全局编录以查找通讯簿信息。如果您获得例外推荐类型设置,则可以尝试全局编录。