文档

Java™教程
隐藏目录
常见问题
路径:Java命名和目录接口
课程:高级LDAP用户主题

常见问题

这节课回答了用户在使用JNDI访问LDAP服务时经常遇到的常见问题。一些常见问题在Naming and Directory Operations课程的Trouble Shooting Tips中有答案。


  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. 传递给上下文方法的名称参数是什么类型?
  19. 我可以将从NameParser得到的名称传递给上下文方法吗?
  20. 我在Context.SECURITY_PRINCIPAL属性中使用的名称与目录之间有什么关系?
  21. 为什么我从目录中读取的名称中有奇怪的引号和转义字符?
  22. 如何获取LDAP条目的完整DN?

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

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

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

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

3. 当我尝试创建初始上下文时,为什么我一直收到CommunicationException

您可能正在与仅支持LDAP v2的服务器进行通信。请参阅JNDI教程的杂项课程,了解如何设置版本号的示例。

4. 如何跟踪LDAP消息?

尝试使用"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教程中的GSS-API/Kerberos v5身份验证部分,了解如何使用Kerberos身份验证的信息。要使用其他身份验证机制,请参阅JNDI教程中的使用任意SASL机制部分。

6. 在更改密码时是否应启用SSL? /

这实际上取决于您使用的目录服务器。某些目录服务器如果未启用SSL,则不允许您更改密码,但有些目录服务器允许。启用SSL可确保密码在通信通道中得到安全保护,因此最好启用SSL。

7. 当我请求一个属性时,为什么返回的是另一个属性?

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

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

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

属性值可以是java.lang.Stringbyte[]。有关以byte[]返回哪些属性值的信息,请参见JNDI教程的杂项部分。要在程序中实现这一点,你可以使用instanceof运算符来检查从LDAP提供程序获取的属性值。

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

目前还不支持。LDAP提供程序仅返回java.lang.Stringbyte[]的属性值。有关详细信息,请参见JNDI教程的杂项部分。

10. 为什么在我的搜索中,将"*"作为属性值无法按预期工作?

当你使用以下形式的search()时,属性值被视为字面值;也就是说,目录条目中的属性应该完全包含该值:search(Name name, Attributes matchingAttrs) 要使用通配符,你应该使用search()的字符串过滤器形式,如下所示:search(Name name, String filter, SearchControls ctls)
search(Name name, String filterExpr, Object[]filterArgs, SearchControls ctls)

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

11. 为什么搜索过滤器中的通配符不总是起作用?

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

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

13. 如何在搜索中传递控制参数?

本教程不解释控制参数。 请查看JNDI教程

14. 如何知道我收到了多少搜索结果?

您必须在枚举结果时计数。 LDAP不提供此信息。

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

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

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

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

17. 传递给ContextDirContext方法的Name参数是什么类型? - CompoundName还是CompositeName

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

18. 我可以将从NameParser获得的名称传递给Context方法吗?

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

19. 我在Context.SECURITY_PRINCIPAL属性中使用的名称与目录之间的关系是什么?

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

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

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

开始使用LdapNameRdn类,这些类可以方便地进行名称操作。

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

您可以使用NameClassPair.getNameInNamespace()



上一页:配置
下一页:目录中的Java对象