本节提供LDAP和JNDI之间映射的详细信息。同时提供使用JNDI访问LDAP服务器的暗示和提示。
X.500,一个CCITT的目录服务器标准,是OSI否为套件的一部分。X.500标准定义了客户端应用程序访问X.500目录的协议,叫做目录访问协议(DAP)。它在开放系统互连(OSI)协议栈的顶层。
因特网委员会认为需要X.500类型的访问但底层的网络基础架构(是TCP/IP而不是OSI)不同,基于X.500 DAP协议设计了一个新协议,叫做轻量级DAP或LDAP。RFC 2251定义了成为版本3的LDAP(LDAPv3),这是它的前身LDAP v2(RFC 1777)的改进。
LDAP协议的目的是容易实现,特别是创建小的简单的客户端。一种尝试简化的成果是大量使用字符串来减少结构的使用。例如DN,在协议中以字符串表示,属性类型名和大多数属性值也是如此。
这个协议包含客户端向服务器发送的请求,对于服务器的应答,不需要按照请求的顺序进行。每一个请求有一个ID,所以请求和应答可以匹配。这个协议可以工作在TCP或UDP中,最常用的是TCP。
因为焦点在客户端,LDAP组织同时定义了DN的字符串表达(RFC 2553),搜索过滤器(RFC 1960),属性语法(RFC 1778),为C语言提供的API(RFC 1823),访问LDAP访问的URL格式(RFC 1959)。
LDAP v3支持国际化,多种认证技术,referral,以及一般的部署技术。使用extensions和controls添加新特性时不需要修改协议。
国际化是通过国际化字符集(ISO 10646)表示协议中的字符串元素(例如DN)。v3与v2不同,v2使用UTF-8编码字符串。
除了匿名,简单(明文密码)认证,LDAPv3使用简单认证以及安全层(SASL)认证架构(RFC 2222)允许在LDAP中使用不同的认证技术。SASL定义了客户端和服务器之间数据交换的认证的挑战-应答协议。
现在定义了一些SASL技术:DIGEST-MD5, CRAM-MD5,匿名,扩展,S/Key, GSSAPI以及Kerberos v4。LDAP v3客户端可以使用任意一种SASL技术,提供给支持这种技术的LDAP v3服务器。而且,新的(还没有定义的)SASL技术可以在不改变LDAP的情况下使用。
referral是服务器发送个客户端的信息,表示请求的信息可以在其他地方发现(很可能是其他服务器)。在LDAP v2中,服务器由服务器处理referral,不返回到客户端。因为实现referral是非常负载的并且可能导致很复杂的客户端。当服务器构建以及部署后,referral就变得十分有用,但不是很多服务器支持服务端的referral处理。所以,使用一种方法修改协议允许返回referral。通过在将referral放置在“partial result”错误应答的错误信息中实现。
LDAP v3显式支持referrals,允许服务器直接向客户端返回referrals。referrals不再本课中介绍,您可以求助于JNDI教程关于符合在应用程序中控制referrals的信息。
LDAP这种普通协议可以用来确保目录客户端和服务器“说同一种语言”。当不同的目录客户端和服务器部署在网络中时,这些实体都说同样的对象是非常有用的。
目录架构描述,在其他东西中间,对象的类型,目录可能有的对象的类型,对象的每个必须的或可选属性。LDAP v3定义架构(RFC 2252 和 RFC 2256)基于X.500标准为了在网络中查找基本对象定义,例如,国家,地区,组织,用户/人,用户组和设备。它定义了客户端访问服务器架构的方法,所以可以发现对象的类型以及服务器支持的属性。
LDAPv3进一步定义了表示属性值的一组语法(RFC 2252)。要编写访问架构信息的Java应用程序,请参考JNDI教程。
除了预定义的所有操作,例如“search”和“modify”之外,LDAPv3定义了“extended”操作。“extended”将请求当作参数并且返回应答。请求中包含标识请求的标识符和请求参数。应答中包含请求执行的结果。“extended”操作中的请求和应答叫做扩展。例如,可以为开始TLS定义扩展,它是客户端向服务器的请求,用来开始Start TLS协议。
扩展可以是标准的(LDAP委员会定义的)或者私有的(由供应商定义)。要编写使用扩展的程序请参考JNDI教程。
添加新特性的另一种方法是使用control。LDAP v3允许通过使用control修改所有操作的行为。一个操作中可以发送任意多个control,同时结果中也可以返回任意数量的control。例如,您可以和“search”操作一起发送排序control,告诉服务器根据“name”属性对结果进行。
和扩展一样,control可以是标准的也可以是私有的。标准control由平台提供。编写使用control的应用程序请参考JNDI教程。
JNDI和LDAP的模型在命名对象时都使用层次结构的名字空间。名字空间中的每一个对象都可能有属性,而且这些属性可以用来搜索对象。在这种层次上,两个模型是类似的,所以JNDI可以对LDAP进行很好的映射也没有什么稀奇的。
您可以将LDAP的条目想象成JNDI的DirContext。每个LDAP条目包含名称和一组属性,以及可选的子条目集合。例如,LDAP条目“o=JNDITutorial”可能有属性“objectclass”和“o”,同时可能有子条目“ou=Groups”和“ou=People”。
在JNDI中,LDAP条目“o=JNDITutorial”可以表示成名为“o=JNDITutorial”的上下文,它有两个子上下文,名叫“ou=Groups”和“ou=People”。LDAP条目属性使用Attributes接口表示,而独立的属性通过Attribute接口表示。
关于LDAP操作如何通过JNDI进行访问的详细信息请参考下一部分。
为了联合查询,您提供给JNDI上下文方法的名称可以跨越多个命名空间。这些叫做混合名字。当使用JNDI访问LDAP服务时,您需要明白字符串中的斜杠(“/”)在JNDI中特殊的含义。如果JNDI条目包含这个字符,需要进行转义(使用“\”)。例如,使用名称“cn=O/R”的LDAP条目在JNDI context的方法中,必须使用“cn=O\\/R”标识。关于名字的更多信息,请参考JNDI教程。LdapName和Rdn类简要介绍了创建和操作LDAP名字的方法。
协议中LDAP的名称总是完全的名字,表示从LDAP命名空间根开始的唯一条目(由服务器定义)。以下是一些LDAP全名的例子:
cn=John Smith, ou=Marketing, o=Some Corporation, c=gb cn=Vinnie Ryan, ou=People, o=JNDITutorial |
然而,在JNDI中,名字是相对的,即,您总是相对于上下文命名对象。例如,您可以相对于上下文“ou=People, o=JNDITutorial”对“cn=Vinnie Ryan”条目进行命名。或者,您可以相对于上下文“o=JNDITutorial”对条目“cn=Vinnie Ryan, ou=People”进行命名。或者,您可以创建初始上下文指向LDAP服务器命名空间的根,然后命名条目“cn=Vinnie Ryan, ou=People, o=JNDITutorial”。
在JNDI中,您同样可以使用LDAP的URL来命名LDAP条目。请参考JNDI教程中的LDAP URL讨论。
LDAP定义了一组操作或请求(RFC 2251)。在JNDI中,这些操作被映射到DirContext和LdapContext接口中,它们都是Context的子接口。例如,当请求DirContext中的方法时。LDAP服务提供者通过将LDAP请求发送给LDAP服务器实现这个操作。
下表描述和LDAP操作对应的JNDI方法:
LDAP操作 |
对应的JNDI方法 |
bind |
这是创建LDAP服务器初始连接的方式,对应JNDI中创建InitialDirContext对象。当应用程序创建初始上下文,它在环境参数中向服务器提供客户端认证信息。要修改一个已经存在上下文的认证信息,使用Context.addToEnvironment()和Context.removeFromEnvironment()。 |
Unbind |
Context.close()用来释放上下文使用的资源。服务提供者的实现和LDAP的unbind操作有一些不同,资源在上下文之间共享,所以关闭上下文当资源被其他上下文使用时就不会释放。如果您的意图是释放所有资源,需要关闭所有上下文。 |
Search |
JNDI中对应方法是DirContext.search()中接收搜索过滤器(RFC 2254)的重载形式。 |
modify |
JNDI中对应方法是DirContext.modifyAttributes()中接收DirContext.ModificationItems数组的重载形式。示例请看修改属性一节。 |
Add |
JNDI中对应方法是DirContext.bind()和DirContext.createSubcontext()。您可以使用它们添加一个新的LDAP条目。使用bind(),您不但需要指定新条目的属性集合同时需要和属性一起的Java对象。示例请参考关联属性的添加、替换绑定一节。 |
Delete |
JNDI中对应的方法是Context.unbind()和Context.destroySubcontext()。您可以使用它们移除LDAP条目。 |
modify DN/RDN |
JNDI中对应方法是Context.rename()。请参考重命名对象一节得到详细信息。 |
compare |
在JNDI中可以使用DirContext.search()代替。示例请参考LDAP比较操作一节。 |
abandon |
当您关闭上下文时,所有没有应答的请求都被放弃。类似的,当关闭NamingEnumeration,相应的LDAP“search”请求也放弃了。 |
Extended操作 |
JNDI中对应的方法是LdapContext.extendedOperation()。详细信息请参考JNDI教程。 |
LDAP定义了一组状态码,它们是由LDAP服务器作为应答发送给客户端的(RFC 2251)。在JNDI中,错误条件由Naming Exceptions子类的检查的异常标识。请参考JNDI异常类概述中的Naming Exceptions。
LDAP状态码 |
含义 |
异常或操作 |
0 |
成功 |
报告成功 |
1 |
操作错误 |
NamingException |
2 |
协议错误 |
CommunicationException |
3 |
达到时间限制 |
TimeLimitExceededException |
4 |
达到大小限制 |
SizeLimitExceededException |
5 |
比较失败 |
被DirContext.search()方法使用,不产生异常。 |
6 |
比较成功 |
被DirContext.search()方法使用,不产生异常。 |
7 |
认证方式不支持 |
AuthenticationNotSupportedException |
8 |
需要更强的认证 |
AuthenticationNotSupportedException |
9 |
只返回部分数据 |
如果环境参数“java.naming.referral”是“ignore”或错误的内容不包含referral,抛出PartialResultException。否则,使用内容创建一个referral。 |
10 |
发生referral |
如果环境参数“java.naming.referral”是“ignore”,则忽略。如果参数是“throw”,抛出ReferralException。如果属性是“follow”,由LDAP提供者处理referral。如果超过“java.naming.ldap.referral.limit”限制,抛出LimitExceededException。 |
11 |
达到管理限制 |
LimitExceededException |
12 |
不支持的关键扩展请求 |
OperationNotSupportedException |
13 |
需要机密信息 |
AuthenticationNotSupportedException |
14 |
SASL绑定中 |
由LDAP提供者在认证过程中使用。 |
16 |
属性不存在 |
NoSuchAttributeException |
17 |
未定义属性类型 |
InvalidAttributeIdentifierException |
18 |
不合适的匹配 |
InvalidSearchFilterException |
19 |
常量违例 |
InvalidAttributeValueException |
20 |
属性值正在使用中 |
AttributeInUseException |
21 |
属性语法错误 |
InvalidAttributeValueException |
32 |
对象不存在 |
NameNotFoundException |
33 |
别名错误 |
NamingException |
34 |
DN语法非法 |
InvalidNameException |
35 |
是叶子节点 |
LDAP提供者使用,通常不产生异常。 |
36 |
别名解析错误 |
NamingException |
48 |
不合适的认证 |
AuthenticationNotSupportedException |
49 |
机密信息非法 |
AuthenticationException |
50 |
访问权限不足 |
NoPermissionException |
51 |
忙 |
ServiceUnavailableException |
52 |
不可得 |
ServiceUnavailableException |
52 |
服务器不愿执行 |
OperationNotSupportedException |
54 |
检测到循环 |
NamingException |
64 |
命名违例 |
InvalidNameException |
65 |
对象类型违例 |
SchemaViolationException |
66 |
非叶子节点不允许操作 |
ContextNotEmptyException |
67 |
不允许在RDN上操作 |
SchemaViolationException |
68 |
条目存在 |
NameAlreadyBoundException |
69 |
va
发表评论
最近访客 更多访客>>最新评论
|
评论