经常问的问题

原文: https://docs.oracle.com/javase/tutorial/jndi/ldap/faq.html

本课程回答用户在使用 JNDI 访问 LDAP 服务时经常遇到的常见问题。在命名和目录操作课程的故障排除提示中回答了一些常见问题。


  1. 上下文:

  2. 多线程访问的上下文安全吗?

  3. 为什么 LDAP 供应器会忽略我的安全环境属性?
  4. 为什么我一直收到 CommunicationException?
  5. 如何获取 LDAP 消息的痕迹?
  6. 如何使用其他身份验证机制,如 Kerberos?
  7. 我应该在更改密码时启用 ssl 吗?

    属性:

  8. 当我要求一个属性时,我会回到另一个属性。为什么?

  9. 我如何知道属性值的类型?
  10. 如何以字符串或字节数组以外的形式返回属性值?
  11. 为什么在搜索中将“*”作为属性值不能正常工作?

    搜索:

  12. 为什么搜索过滤器中的通配符始终不起作用?

  13. 当我知道目录中有更多条目时,为什么我只返回 n 条目数?
  14. 如何通过搜索传递控件?
  15. 我如何知道我收到了多少搜索结果?

    名称:

  16. 为什么我的 SearchResult 中有一个空字符串作为名称?

  17. 为什么我在 SearchResult 中将 URL 字符串作为名称?
  18. 传递给上下文方法的 Name 参数是什么类型的?
  19. 我可以将从 NameParser 返回的名称传递给 Context 方法吗?
  20. 我用于Context.SECURITY_PRINCIPAL属性的名称和目录之间的关系是什么?
  21. 为什么我从目录中读取的名称中出现了奇怪的引号和转义?
  22. 如何获取 LDAP 条目的完整 DN?

答案取决于实现。这是因为 ContextDirContext接口没有指定同步要求。 JDK 中的 LDAP 实现针对单线程访问进行了优化。如果你有多个线程访问相同的Context实例,那么每个线程在使用它时需要锁定Context实例。这也适用于从同一Context实例派生的任何NamingEnumeration 。但是,多个线程可以在没有锁的情况下同时访问*不同的 _ Context实例(甚至是那些从相同的初始上下文派生的实例)。

Context.SECURITY_CREDENTIALS “java.naming.security,为什么 LDAP 供应器会忽略我的安全环境属性。凭证“)属性还是将其设置为空字符串?

如果你提供一个空字符串,空字节 / char数组,或nullContext.SECURITY_CREDENTIALS环境属性,那么即使Context.SECURITY_AUTHENTICATION属性设置为“simple”,也会发生匿名绑定。这是因为对于简单身份验证,LDAP 要求密码非空。如果未提供密码,则协议会自动将身份验证转换为“无”

CommunicationException

您可能正在与仅支持 LDAP v2 的服务器通信。有关如何设置版本号的示例,请参阅 JNDI 教程的其他课程。

尝试使用“com.sun.jndi.ldap.trace.ber”环境属性。如果此属性的值是java.io.OutputStream的实例,则 LDAP 供应器发送和接收的 BER 缓冲区的跟踪信息将写入该流。如果属性的值为null ,则不写入跟踪输出。

例如,以下代码将跟踪输出发送到System.err

  1. env.put("com.sun.jndi.ldap.trace.ber", System.err);

有关如何使用 Kerberos 身份验证的信息,请按照 JNDI 教程的 GSS-API / Kerberos v5 身份验证中的说明进行操作。要使用其他身份验证机制,请参阅 JNDI 教程的“使用任意 SASL 机制”部分。

/

这实际上取决于您使用的目录服务器。如果未启用 SSL 但某些目录服务器允许更改密码,则某些目录服务器将不允许您更改密码。启用 S​​SL 以在通信通道中保护您的密码是件好事。

您正在使用的属性名称可能是另一个属性的同义词。在这种情况下,LDAP 服务器可能会返回规范属性名称而不是您提供的名称。当您查看服务器返回的属性时,您需要使用规范名称而不是同义词。

例如,“fax”可能是规范属性名称“facsimiletelephonenumber”的同义词。如果您要求“传真”,服务器将返回名为“facsimiletelephonenumber”的属性。有关同义词和有关属性名称的其他问题的详细信息,请参阅命名和目录操作课程。

属性的值可以是java.lang.Stringbyte [] 。有关哪些属性值作为byte []返回的信息,请参见 JNDI 教程的其他部分。要以编程方式执行此操作,可以使用instanceof运算符来检查从 LDAP 供应器返回的属性值。

目前你不能。 LDAP 供应器仅返回java.lang.Stringbyte []的属性值。请参阅 JNDI 教程的其他部分。

当您使用以下形式的search()时,属性值被视为文字;也就是说,目录条目中的属性应该包含该值: 搜索(名称,属性 matchingAttrs) 要使用通配符,您应该使用[的字符串过滤形式] HTG6] search(),如下。 搜索(名称,字符串过滤器,SearchControls ctls) 搜索(名称名称,String filterExpr,Object [] filterArgs,SearchControls ctls)

对于最后一种形式,通配符必须出现在filterExpr参数中,而不是出现在filterArgs中。 filterArgs中的值也被视为文字。

出现在属性值之前或之后的通配符(例如“attr = * I *”)表示服务器将使用属性的子字符串匹配规则搜索匹配的属性值。如果属性的定义没有子字符串匹配规则,则服务器无法找到该属性。您必须使用相等或“现在”过滤器进行搜索。

某些服务器配置为限制可以返回的条目数。其他人也限制了搜索期间可以检查的条目数。检查您的服务器配置。

本教程不解释控件。查看 JNDI 教程

在列举结果时,您必须保持计数。 LDAP 不提供此信息。

SearchResult 中有一个空字符串作为名称?

getName() 总是将相对的名称返回到搜索的目标上下文。因此,如果目标上下文满足搜索过滤器,则返回的名称将为“”(空名称),因为这是相对于目标上下文的名称。有关详细信息,请参阅搜索结果部分。

SearchResult 中有一个 URL 字符串作为名称?

通过跟随别名或引用来检索 LDAP 条目,因此其名称是 URL。有关详细信息,请参阅搜索结果课程。

名称 参数传递给 上下文DirContext方法? - 化合物名复合名称

字符串表单接受复合名称的字符串表示形式。也就是说,使用字符串名称相当于调用new CompositeName(stringName)并将结果传递给Context / DirContext方法。 Name参数可以是实现Name接口的任何对象。如果它是CompositeName的实例,则将该名称视为复合名称;否则,它被视为复合名称。

NameParser 的名称传递给 上下文 方法吗?

这与前一个问题有关。是的你可以。 NameParser.parse() 返回实现Name接口的复合名称。此名称可以传递给Context方法,该方法将其解释为复合名称。

Context.SECURITY_PRINCIPAL 属性和目录的名称之间的关系是什么?

您可以将主体名称视为来自与目录不同的命名空间。有关 LDAP 身份验证机制的详细信息,请参阅 RFC 2829安全部分。 JDK 中的 LDAP 服务供应器接受字符串主体名称,它直接传递给 LDAP 服务器。一些 LDAP 服务器接受 DN,而其他服务器支持 RFC 2829 提出的方案。

JDK 中的 LDAP 名称解析器在引用规则方面是保守的,但它仍然生成“正确”的名称。另外,请记住 NamingEnumeration返回的条目名称是可以传递回ContextDirContext方法的复合名称。因此,如果名称包含与复合名称语法冲突的字符(例如正斜杠字符“/”),则 LDAP 供应器将提供编码以确保将斜杠字符视为 LDAP 名称的一部分而不是作为复合名称分隔符。

开始使用 LdapNameRdn类,可以轻松进行名称操作。

您可以使用 NameClassPair.getNameInNamespace()