经常问的问题

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


Contexts:

Attributes:

Searches:

Names:


1.上下文对于多线程访问是否安全,还是需要锁定/同步对上下文的访问?

答案取决于实现方式。这是因为ContextDirContextinterface未指定同步要求。 JDK 中的 LDAP 实现针对单线程访问进行了优化。如果您有多个线程访问同一个Context实例,则每个线程在使用时都需要锁定Context实例。这也适用于从同一Context实例派生的任何NamingEnumeration。但是,多个线程可以并发地访问*不同的Context实例(甚至是从同一初始上下文派生的实例),而无需锁定。

2.如果未设置 LDAP 提供程序,为什么 LDAP 提供程序会忽略我的安全环境属性 Context.SECURITY_CREDENTIALS("java\.naming\.security\.credentials")属性还是将其设置为空字符串?

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

3.为什么我会不断收到 CommunicationException当我try创建初始上下文时?

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

4.如何跟踪 LDAP 消息?

try使用"com\.sun\.jndi\.ldap\.trace\.ber"环境属性。如果此属性的值是java\.io\.OutputStream的实例,则将 LDAP 提供程序发送和接收的有关 BER 缓冲区的跟踪信息写入该流。如果该属性的值为null,则不会写入任何跟踪输出。

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

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

5.如何使用其他验证机制,例如 Kerberos?

请遵循JNDI Tutorial的 GSS-API/Kerberos v5 身份验证中的说明,以获取有关如何使用 Kerberos 身份验证的信息。要使用其他身份验证机制,请参阅JNDI tutorial的“使用任意 SASL 机制”部分。

6.更改密码时应该启用 SSL 吗? /

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

7.当我要求一种属性时,我又得到另一种。为什么?

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

例如,"fax"可能是规范属性名称"facsimiletelephonenumber"的同义词。如果要求"fax",则服务器将返回名为"facsimiletelephonenumber"的属性。有关同义词以及与属性名称有关的其他问题的详细信息,请参见命名和目录操作节。

8.如何知道属性值的类型?

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

9.如何以非字符串 或字节数组的形式获取属性的值?

目前您还不能。 LDAP 提供程序仅返回java\.lang\.Stringbyte\[\]的属性值。请参阅JNDI Tutorial的“其他”部分。

10.为什么将“ *”作为属性值不能按我的预期工作?

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

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

11.为什么搜索过滤器中的通配符不总是有效?

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

12.当我知道目录中还有更多条目时,为什么只返回 n 个条目?一些服务器被配置为限制可以返回的条目数。其他限制了在搜索过程中可以检查的条目数。检查您的服务器配置。

13.如何通过搜索传递控件?

本教程中没有解释控件。签出JNDI Tutorial

14.如何确定我得到了多少搜索结果?

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

15.为什么我在自己的名字中得到一个空字符串SearchResult?

getName()始终返回搜索的“目标上下文”的名称“相对”。因此,如果目标上下文满足搜索过滤条件,则返回的名称将为“”(空名称),因为这是相对于目标上下文的名称。有关详情,请参见Search Results部分。

16.为什么我在自己的名字中得到一个 URL 字符串SearchResult?

通过跟随别名或引用来检索 LDAP 条目,因此其名称为 URL。有关详情,请参见Search Results类。

17.什么是 Name参数传递给ContextDirContext方法? -CompoundNameCompositeName

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

18.我可以传递从我那里回来的名字吗 NameParserContext方法?

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

19.我使用的名称之间有什么关系 Context.SECURITY_PRINCIPAL属性和目录?

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

20.从目录中读取的名称为什么会有奇怪的引号和转义符?

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

开始使用启用简单名称操作的LdapNameRdn类。

21.如何获取 LDAP 条 Object 完整 DN?

您可以使用NameClassPair.getNameInNamespace()