5

我将 LDAP DirContext.search(...) 设置为忽略引用,但是当我调用 NamingEnumeration.hasMore() 时仍然会遇到引用异常。

Exception in thread "main" javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'DC=company,DC=com'
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2846)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2820)
    at com.sun.jndi.ldap.LdapNamingEnumeration.getNextBatch(LdapNamingEnumeration.java:129)
    at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:198)
    at com.sun.jndi.ldap.LdapNamingEnumeration.hasMore(LdapNamingEnumeration.java:171)

我可以告诉 DirContext.search 忽略引用,以便 NamingEnumeration.hasMore() 返回 false 而不是抛出异常吗?

这是剪断:

import javax.naming.*;
import javax.naming.directory.*;

Properties p = new Properties();
p.setProperty(Context.INITIAL_CONTEXT_FACTORY, ldapInitContextFactory);
p.setProperty(Context.PROVIDER_URL, ldapURL);
p.setProperty(Context.SECURITY_CREDENTIALS, ldapPassword);
p.setProperty(Context.SECURITY_PRINCIPAL, ldapUser);
p.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
p.setProperty(Context.REFERRAL, "ignore");
DirContext ctx = new InitialDirContext(p);

SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setDerefLinkFlag(false);

NamingEnumeration e = ctx.search(ldapBaseDN, ldapQuery, null, searchControls);

for (; e.hasMore();) {
    SearchResult sr = (SearchResult) e.next();
    System.out.println("\nSearch Result: " + sr.getName());
}

注意:如果我启用推荐,我会在调用 NamingEnumeration.hasMore() 时收到 LdapReferralException 异常。

4

2 回答 2

8
javax/naming/NamingEnumeration.java
public interface NamingEnumeration<T> extends Enumeration<T> {
    public boolean hasMore() throws NamingException;
    public T next() throws NamingException;
    ...
}

java/util/Enumeration.java
public interface Enumeration<E> {
    boolean hasMoreElements();
    E nextElement();
}

调用 e.hasMoreElements() 而不是 e.hasMore() 可以解决问题。也就是说,当有引用时,它返回 false(而不是抛出异常)。

但是,这不是一个最佳解决方案,因为我们可能会遗漏其他真正的 NamingException 异常(例如 CommunicationException)。

我仍然想找到告诉 DirContext.search 忽略引用的正确方法,以便 NamingEnumeration.hasMore() 返回 false 而不是抛出异常。任何想法?

我在http://download.java.net/openjdk/jdk6/ -> openjdk-6-src-b24-14_nov_2011.tar.gz下载了 JDK 源代码,但是此源代码与 JDK 二进制文件不完全对应,请参阅如何找到 JDK1.6 二进制文件的确切来源(包括 com.sun.jndi.*)

从下面的这个JDK源代码来看,当有引用时,似乎不可能得到“假”而不是异常。

./jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java
protected void processReturnCode(LdapResult res, Name resolvedName, Object resolvedObj, Name remainName, Hashtable envprops, String fullDN) throws NamingException {
    NamingException e;

    switch (res.status) {
    case LdapClient.LDAP_SUCCESS:

        // handle Search continuation references
        if (res.referrals != null) {
            msg = "Unprocessed Continuation Reference(s)";

            if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
                e = new PartialResultException(msg);
                break;
            }
        [...]
    }
    [...]
    throw e;
}

但我仍然不确定。

我认为我们可以告诉 DirContext.search 忽略引用是有道理的,这样 NamingEnumeration.hasMore() 返回 false 而不是抛出异常。

任何想法?

于 2012-04-24T22:17:03.180 回答
1

据我所知,有一种方法可以忽略引用,这在处理 Active Directory LDAP 操作时特别有用。您必须创建并注入一个新的LdapTemplate(使用已配置的 构建),而不是从头开始ContextSource创建自己的。InitialDirContext我不知道这是否与您的设置兼容。我希望这有帮助。

来自 Spring LDAP CoreLdapTemplate 文档

AD 服务器显然无法自动处理引荐,这会导致PartialResultException在搜索中遇到引荐时抛出 a。为避免这种情况,请将ignorePartialResultException属性设置为true

于 2018-07-11T01:01:16.373 回答