经常问的问题
本类回答了用户在使用 JNDI 访问 LDAP 服务时经常遇到的常见问题。在“命名和目录操作”类的故障排除技巧中回答了一些常见问题。
Contexts:
Attributes:
Searches:
Names:
1.上下文对于多线程访问是否安全,还是需要锁定/同步对上下文的访问?
答案取决于实现方式。这是因为Context和DirContextinterface未指定同步要求。 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的其他类。
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);
请遵循JNDI Tutorial的 GSS-API/Kerberos v5 身份验证中的说明,以获取有关如何使用 Kerberos 身份验证的信息。要使用其他身份验证机制,请参阅JNDI tutorial的“使用任意 SASL 机制”部分。
这实际上取决于您使用的目录服务器。如果未启用 SSL,某些目录服务器将不允许您更改密码,但某些服务器却允许。启用 SSL 以在通信通道中保护密码是很好的。
您使用的属性名称可能是另一个属性的同义词。在这种情况下,LDAP 服务器可能返回规范属性名称,而不是您提供的名称。当您查看服务器返回的Attributes
时,需要使用规范名称而不是同义词。
例如,"fax"
可能是规范属性名称"facsimiletelephonenumber"
的同义词。如果要求"fax"
,则服务器将返回名为"facsimiletelephonenumber"
的属性。有关同义词以及与属性名称有关的其他问题的详细信息,请参见命名和目录操作节。
属性的值可以是java\.lang\.String
或byte\[\]
。有关哪些属性的值以byte\[\]
返回的信息,请参见JNDI Tutorial的“其他”部分。要以编程方式执行此操作,可以使用instanceof
运算符来检查从 LDAP 提供程序获取的属性值。
目前您还不能。 LDAP 提供程序仅返回java\.lang\.String
或byte\[\]
的属性值。请参阅JNDI Tutorial的“其他”部分。
当使用以下形式的search\(\)
时,属性值被视为 Literals;也就是说,目录条目中的属性应包含该值:搜索(名称,属性 attributeAttrs)要使用通配符,应使用search\(\)
的字符串 过滤器形式,如下所示。 搜索(名称,字符串 过滤器,SearchControls ctls)
搜索(名称,字符串filterExpr,对象[] filterArgs,SearchControls ctls)
对于最后一种形式,通配符必须出现在filterExpr
参数中,而不能出现在filterArgs
中。 filterArgs
中的值也被视为 Literals。
在属性值之前或之后(例如"attr=\*I\*"
)出现的通配符表示服务器将通过使用属性的子字符串 匹配规则来搜索匹配的属性值。如果属性的定义没有子字符串 匹配规则,则服务器找不到该属性。您必须使用等式或“当前”过滤器进行搜索。
12.当我知道目录中还有更多条目时,为什么只返回 n 个条目?一些服务器被配置为限制可以返回的条目数。其他限制了在搜索过程中可以检查的条目数。检查您的服务器配置。
本教程中没有解释控件。签出JNDI Tutorial。
在对结果进行枚举时,您必须保持计数。 LDAP 不提供此信息。
15.为什么我在自己的名字中得到一个空字符串SearchResult?
getName()始终返回搜索的“目标上下文”的名称“相对”。因此,如果目标上下文满足搜索过滤条件,则返回的名称将为“”(空名称),因为这是相对于目标上下文的名称。有关详情,请参见Search Results部分。
16.为什么我在自己的名字中得到一个 URL 字符串SearchResult?
通过跟随别名或引用来检索 LDAP 条目,因此其名称为 URL。有关详情,请参见Search Results类。
17.什么是 Name参数传递给Context和DirContext方法? -CompoundName或CompositeName?
字符串 形式接受复合名称的字符串 表示形式。也就是说,使用字符串 名称等效于调用new CompositeName\(stringName\)
并将结果传递给Context
/DirContext
方法。 Name
参数可以是实现Name
interface的任何对象。如果它是CompositeName
的实例,则该名称将被视为复合名称;否则,将其视为复合名称。
18.我可以传递从我那里回来的名字吗 NameParser至Context方法?
这与上一个问题有关。是的你可以。 NameParser.parse()返回实现Name
interface的复合名称。该名称可以传递给Context
方法,该方法会将其解释为复合名称。
19.我使用的名称之间有什么关系 Context.SECURITY_PRINCIPAL属性和目录?
您可以认为主体名称来自与目录不同的名称空间。有关 LDAP 身份验证机制的详细信息,请参见RFC 2829和Security部分。 JDK 中的 LDAP 服务提供者接受字符串 主体名称,它将直接传递给 LDAP 服务器。一些 LDAP 服务器接受 DN,而其他一些则支持RFC 2829提出的方案。
JDK 中的 LDAP 名称解析器在引用规则方面比较保守,但仍会生成“正确的”名称。另外,请记住,由NamingEnumerations返回的条 Object 名称是可以传递回Context
和DirContext
方法的复合名称。因此,如果名称包含与组合名称语法冲突的字符(例如正斜杠字符“ /”),则 LDAP 提供程序将提供一种编码,以确保将斜杠字符视为 LDAP 名称的一部分而不是使用复合名称分隔符。
您可以使用NameClassPair.getNameInNamespace()。