【IT168技术文档】
目前目录服务器主要有:
Mircrosoft的活动目录AD
SUN ONE的目录服务器
Novell的NDS
目录服务器是产品,它看起来就象一个树形的数据库,里面可以存各式各样的信息,形象点说象注册表,不过比注册表更强大,更安全!
目录服务器实现手段不同,不过都遵守LDAP协议。
LDAP称为轻型目录存取协议,现在比较好的版本是V3。主要的目录服务器都支持此协议,所以程序基本可以通用。问题是用什么来唯一标记一种资源?有的服务器用一个id,有的服务器用email地址。这回麻烦了,资源的定义各个服务器不同,LDAP的互操作性比较差劲儿。现在IETF已经意识到这点,正在统一此标准。
LDAP数据存在目录信息树里。每条是一个记录项,一个entry,每条有唯一的识别名DN(distinguished)。我们看图:

这张图表示了一个企业的组织层次结构。树根表示企业名,比如 NetScaperoot,下一级表示企业的某个层次的部门,比如dc=jssvc,dc=com,代表笔者的机器jssvc.com。ou表示一个子部门,现在名字是groups,最后用户标识是Zeng。
dc=jssvc,dc=com ou=groups uid=Zeng o=netscaperootuid=Zeng,ou=groups,dc=jssvc,dc=com,o=netscaperoot
上面的名字是某结点到根的路径,它唯一地标识了企业中的某资源,它不可能重名。在ldap中,它称为一个entry。
现在我们知道,本章的目的就是要教大家如何利用LDAP服务器来管理企业里的资源信息。这些操作有:
连接至服务器
访问服务器,接受验证
搜索服务器
加新记录
删除记录
修改记录
目录服务的具体操作
连接LDAP服务器
验证并连接LDAP服务器
LDAP服务器存有企业资源的所有信息。显然不是谁都能访问的。众多信息对普通用户而言是只读的,比如文件系统位置,打印机信息,部门信息等。 连接LDAP服务器时安全考虑大概有两层:
连接到LDAP服务器进行验证,称为 authenticate。客户程序提供用户名密码,告诉服务器你是谁,你想做什么。
连接之后,用户也并非为所欲为。LDAP使用 access control 来控制哪些是某用户可以做的,哪些是不能的。Access Control List的目的就是这个。大家在SUN ONE服务器的目录旁边经常看见的“ACL”字样就是存取控制列表。
安全级别不同,验证强度不同。LDAP版本3提供了以下几种验证方法:
-anonymous 匿名方式,不用用户名密码
-simple 简单方式,用明码提供用户密码。马马虎虎的场合用。
-Simple Authentication and Security Layer (RFC 2222).SASL。这是一个规范,只要ldap和客户端达成协议,可以用各种安全模式交换验证信息。比如
-Digest MD5(非常常见)
-External
-kerberos v4/v5(Windows2000里用的)
-等等
本章篇幅所限,只能说说简单的验证模式。而且SUN ONE也不支持Kerberos,要用AD处理。至于验证成功后安全传输普通数据,请参考 SSL 连接。我有例子程序实现了SSL连接和传输。上课不讲了。 下面看一个简单的验证程序。
//Conn.java:
import java.util.Hashtable;
import java.util.Enumeration;
import javax.naming.*;
import javax.naming.directory.*;
![]()
![]()
/**//**
*This example shows how to add attributes in the ldap server by adding an object.
*Creates 7 instances of the user object and stores them in the database
*/
public class ConnOpenLDAP...{
public static void main(String args[])...{
try ...{
//Hashtable for environmental information
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
![]()
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=Manager,o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "secret");//密码是secret
![]()
//Get a reference to a directory context
DirContext ctx = new InitialDirContext(env);
System.out.println(“Connection Successful!”);
} catch(Exception e)
...{
e.printStackTrace();
System.exit(1);
}
![]()
}