LDAP

近来在接触LDAP,感觉很有意思,在学习的时候收集了些资料,发上来分享。

有兴趣的可以自己配一个LDAP服务器玩玩。



首先是要配置一个LDAP服务器,Windows上对LDAP的配置资料不多。

2楼是Windows上对LDAP服务器配置的资料

3楼是对LDAP完整的增删改查例子。

4楼是Java6.0 API for LDAP中文概述


1楼主要是java的LDAP登录验证.还要Spring Security的LDAP认证



什么是LDAP?

LDAP的英文全称是Lightweight Directory Access Protocol,一般都简称为LDAP。LDAP通常被公司用作用户信息的中心资源库,同时也被当作一种认证服务。 它也可以为应用用户储存角色信息。


在企业范围内实现LDAP可以让运行在几乎所有计算机平台上的所有的应用程序从 LDAP目录中获取信息。LDAP目录中可以存储各种类型的数据:电子邮件地址、邮件路由信息、人力资源数据、公用密匙、联系人列表,等等。通过把 LDAP目录作为系统集成中的一个重要环节,可以简化员工在企业内部查询信息的步骤,甚至连主要的数据源都可以放在任何地方。

范例:

1 一共两个java类,加一个配置文件
2
3 LDAP.java---------------连接LDAP服务器,判断用户名密码正确与否
4
5 UMParas.java----------jDom解析xml配置文件
6
7 ldapconfig.xml---------配置文件,里面有服务器的参数信息
8
9 LDAP.java 代码
10 package ldap2;
11
12 import java.util.Hashtable;
13 import javax.naming.AuthenticationException;
14 import javax.naming.Context;
15 import javax.naming.InitialContext;
16 import javax.naming.NamingException;
17 import javax.naming.directory.DirContext;
18
19 public class LDAP {
20
21 private Hashtable env = null;
22
23 private DirContext ctx = null;
24
25 private boolean islogin = false;
26
27 StringBuffer url;
28
29 String host;
30
31 String port;
32
33 String admin;
34
35 String password;
36
37 String baseDN;
38
39 public LDAP(String id, String pwd) {
40 try {
41 host = UMParas.getPara("hostname");
42 port = UMParas.getPara("port");
43 baseDN = UMParas.getPara("basedn");
44 admin = UMParas.getPara("admin");
45 password = UMParas.getPara("pwd");
46 url = new StringBuffer("LDAP://");
47 url.append(host).append(":").append(port);
48 url.append("/").append(baseDN);
49
50 } catch (Exception e) {
51 e.printStackTrace();
52 System.out.println("");
53 }
54 // pwd="secret";
55 env = new Hashtable();
56
57 env.put("java.naming.factory.initial",
58 "com.sun.jndi.ldap.LdapCtxFactory");
59 env.put("java.naming.provider.url", url.toString());
60 env.put(Context.SECURITY_AUTHENTICATION, "simple");
61
62 env.put("java.naming.security.principal", admin);
63 env.put("java.naming.security.credentials", password);
64 System.out.println("-------------");
65 }
66
67 public boolean checkAd() { //admin用户验证
68 try {
69 System.out.println("-----ddd--------");
70 InitialContext iCnt = new InitialContext(env);
71 System.out.println("-------eee------");
72 islogin = true;
73 } catch (AuthenticationException aue) {
74 // aue.printStackTrace();
75 islogin = false;
76
77 } catch (NamingException e) {
78
79 e.printStackTrace();
80 } catch (Exception eee) {
81 eee.printStackTrace();
82
83 } finally {
84 try {
85 ctx.close();
86 } catch (Exception ie) {
87
88 }
89 }
90 return islogin;
91 }
92
93 public boolean userLogin(String userName, String password) { //用户验证。
94 Hashtable envi = new Hashtable();
95 try {
96 envi.put("java.naming.factory.initial",
97 "com.sun.jndi.ldap.LdapCtxFactory");
98 envi.put("java.naming.provider.url", url.toString());
99 envi.put(Context.SECURITY_AUTHENTICATION, "simple");
100 envi.put("java.naming.security.principal", userName);
101 envi.put("java.naming.security.credentials", password);
102 InitialContext iCnt = new InitialContext(envi);
103 return true;
104 } catch (Exception e) {
105 //e.printStackTrace();
106 return false;
107 } finally {
108 try {
109 ctx.close();
110 } catch (Exception ie) {
111
112 }
113 }
114 }
115 }
116
117
118
119
120
121 UMParas.java 代码
122 package ldap2;
123
124 import java.io.*;
125 import java.util.*;
126 import org.jdom.*;
127 import org.jdom.input.SAXBuilder;
128
129 public class UMParas {
130
131 private static HashMap prop;
132
133 private static long lastLoadTime;
134
135 private static long interval = 0x186a0L; //refresh per 100 second
136 // static Class class$0; /* synthetic field */
137
138 public UMParas() {
139 }
140
141 //input an para and return the result
142 public static synchronized String getPara(String paras)
143 throws IllegalArgumentException {
144 if (paras == null || paras.trim().length() == 0)
145 throw new IllegalArgumentException("Parameter's value invalid.");
146 long currentTime = System.currentTimeMillis();
147 if (prop == null || currentTime - lastLoadTime > interval)
148 reloadDom();
149 Object obj = prop.get(paras);
150 if (obj != null)
151 return (String) obj;
152 else
153 return null;
154 }
155
156 //load the xml file
157 private static synchronized void reloadDom() {
158 if (prop == null)
159 prop = new HashMap();
160 SAXBuilder builder = new SAXBuilder();
161 Document read_doc = null;
162 try {
163 read_doc = builder.build(UMParas.class
164 .getResource("ldapconfig.xml"));
165 } catch (FileNotFoundException e) {
166 e.printStackTrace();
167 } catch (JDOMException e) {
168 e.printStackTrace();
169 } catch (IOException e) {
170 e.printStackTrace();
171 }
172 Element rootElement = read_doc.getRootElement();
173 List list = rootElement.getChildren("para");
174 for (Iterator i = list.iterator(); i.hasNext();) {
175 Element current = (Element) i.next();
176 List item = current.getChildren("item");
177 Attribute code;
178 Attribute value;
179 for (Iterator j = item.iterator(); j.hasNext(); prop.put(code
180 .getValue(), value.getValue())) {
181 Element init = (Element) j.next();
182 code = init.getAttribute("code");
183 value = init.getAttribute("value");
184 }
185
186 }
187 System.out.println("load sucess");
188 lastLoadTime = System.currentTimeMillis();
189 }
190
191 public static void main(String args[]) {
192 System.out.println(getPara("hostname"));
193 }
194
195 }




[xml]
ldapconfig.xml 代码
200 <?xml version="1.0" encoding="GBK"?>
201 <sys_para>
202 <para>
203 <item code="hostname" value="192.168.1.106" description="LDAP服务器IP"/>
204 <item code="port" value="10389" description="服务器端口"/>
205 <item code="admin" value="uid=admin,ou=system" description="管理员帐号"/>
206 <item code="pwd" value="secret" description="密码"/>
207 <item code="basedn" value="ou=system" description="组织名(基准DN)"/>
208 </para>
209 </sys_para>

[/xml]

2:Windows下安装使用openldap

openldap 比起其他商业目录服务器(比如 IBM Directory Server),特别的轻巧,十分适合于本地开发测试用,在产品环境中的表现也很优秀。

openldap 软件在它的官方网站 http://www.openldap.org, 不过下载过来是源代码,并没有包含 win32 下的 Makefile 文件,只提供了在 Unix/Linux 下编译用的 Makefile。所以相应的在网上介绍在 windows 下安装使用 openldap 的资料比较少,而在 Unix/Linux 下应用文档却很丰富。

本文实践了在 Windows 下安装配 openldap,并添加一个条目,LdapBrowser 浏览,及 Java 程序连接 openldap 的全过程。

1. 下载安装 openldap for windows,当前版本2.2.29
下载地址:http://download.bergmans.us/openldap/openldap-2.2.29/openldap-2.2.29-db-4.3.29-openssl-0.9.8a-win32_Setup.exe
相关链接:http://lucas.bergmans.us/hacks/openldap/
安装很简单,一路 next 即可,假设我们安装在 c:\openldap

2. 配置 openldap,编辑 sldap.conf 文件
1) 打开 c:\openldap\sldap.conf,找到
include C:/openldap/etc/schema/core.schema,在它后面添加
include C:/openldap/etc/schema/cosine.schema
include C:/openldap/etc/schema/inetorgperson.schema

接下来的例子只需要用到以上三个 schema,当然,如果你觉得需要的话,你可以把其他的 schema 全部添加进来
include C:/openldap/etc/schema/corba.schema
include C:/openldap/etc/schema/dyngroup.schema
include C:/openldap/etc/schema/java.schema
include C:/openldap/etc/schema/misc.schema
include C:/openldap/etc/schema/nis.schema
include C:/openldap/etc/schema/openldap.schema

2) 还是在 sldap.conf 文件中,找到
suffix "dc=my-domain,dc=com"
rootdn "cn=Manager,dc=my-domain,dc=com"
把这两行改为
suffix "o=tcl,c=cn"
rootdn "cn=Manager,o=tcl,c=cn"

suffix 就是看自己如何定义了,后面步骤的 ldif 文件就必须与它定义了。还要注意到这个配置文件中有一个 rootpw secret,这个 secret 是 cn=Manager 的密码,以后会用到,不过这里是明文密码,你可以用命令: slappasswd -h {MD5} -s secret 算出加密的密码 {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== 取代配置中的 secret。

3. 启动 openldap
CMD 进入到 c:\openldap 下,运行命令 sldapd -d 1
用可以看到控制台下打印一片信息,openldap 默认是用的 Berkeley DB 数据库存储目录数据的。

4. 建立条目,编辑导入 ldif 文件
1) 新建一个 ldif(LDAP Data Interchanged Format) 文件(纯文本格式),例如 test.ldif,文件内容如下:

dn: o=tcl,c=cn
objectClass: dcObject
objectClass: organization
o: tcl
dc: com

dn: uid=Unmi, o=tcl,c=cn
uid: Unmi
objectClass: inetOrgPerson
mail: fantasia@sina.com
userPassword:: MTIzNDU2
labeledURI: http://unmi.blogcn.com
sn: Qiu
cn: 隔叶黄莺

2) 执行命令:ldapadd -x -D "cn=manager,o=tcl,c=cn" -w secret -f test.ldif
导入组织信息和一个用户 uid=Unmi

5. LdapBrowser 浏览
可点击链接 http://www.blogjava.net/Files/Unmi/LdapBrowser282.rar 下载,其中已配置好了 OpenLdap_Localhost

1) 设置如下图所示:

[upload=jpg,unmi,20070727022653358.jpg]UploadFile/2010-1/201012623142720244.jpg[/upload]
指定了 Host 为 localhost 之后,可以点击 Fetch DNs 按钮显示出 o=tcl,c=cn 来,如果要能在 LdapBrowser 中对数据能修改就不能用 Anonymous bind, 必须填上 User DN: cn=manager,Passwer: secret。

3:一个完整的ldap操作的例子



以下是对ldap中进行连接,人员的增删改查的过程。希望对初学者有一定的帮助

package net.risesoft.ldap;

import java.util.Enumeration;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class LdapTest {
public static void main(String[] args) {
String account = "admin";
String password = "1";
String root = "o=com"; // root

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/" + root);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=" + account + "," + root);
env.put(Context.SECURITY_CREDENTIALS, password);

DirContext ctx = null;
try {
// 链接ldap
ctx = new InitialDirContext(env);
System.out.println("ldap认证成功");

// 3.添加节点
String newUserName = "user2";
BasicAttributes attrsbu = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectclass");
objclassSet.add("person");
objclassSet.add("top");
objclassSet.add("organizationalPerson");
objclassSet.add("inetOrgPerson");
attrsbu.put(objclassSet);
attrsbu.put("sn", newUserName);
attrsbu.put("uid", newUserName);
ctx.createSubcontext("cn=" + newUserName, attrsbu);

// 5.修改节点
account = "user2";
String newDisplayName = "newDisplayName";
ModificationItem modificationItem[] = new ModificationItem[1];
modificationItem[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("displayName", newDisplayName));
ctx.modifyAttributes("cn=" + account, modificationItem);

// 查询节点
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
// constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
NamingEnumeration en = ctx.search("", "cn=user2", constraints); // 查询所有用户
while (en != null && en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult si = (SearchResult) obj;
System.out.println("name: " + si.getName());
Attributes attrs = si.getAttributes();
if (attrs == null) {
System.out.println("No attributes");
} else {
for (NamingEnumeration ae = attrs.getAll(); ae.hasMoreElements();) {
Attribute attr = (Attribute) ae.next();
String attrId = attr.getID();

for (Enumeration vals = attr.getAll(); vals.hasMoreElements();) {
System.out.print(attrId + ": ");
Object o = vals.nextElement();
if (o instanceof byte[])
System.out.println();// new
// String((byte[])o)
else
System.out.println(o);
}
}
}
} else {
System.out.println(obj);
}
System.out.println();
}

// 4.删除节点
account = "user2";
ctx.destroySubcontext("cn=" + account);

} catch (javax.naming.AuthenticationException e) {
System.out.println("认证失败");
} catch (Exception e) {
System.out.println("认证出错:");
e.printStackTrace();
}

if (ctx != null) {
try {
ctx.close();
} catch (NamingException e) {
// ignore
}
}
System.exit(0);
}
}

4:
从JDK5.0开始,对LDAP协议的数据访问操作就被集成在javax的扩展API包中,并随同JDK一并发布,这一章节,我们主要介绍API包中的类信息。
javax.naming.directory 包的结构



[upload=gif,1.gif]UploadFile/2010-1/201012623272948675.gif[/upload]

常用API解析

javax.naming.directory.InitialDirContext,初始化目录服务上下文类
该类是LDAP数据内容的操作工具类,通过该类可以执行绑定LDAP服务器、新增LDAP条目、获取条目实例、修改条目属性、删除条目和根据条件搜索条目等操作。常用方法说明如下:

初始化LDAP 目录服务上下文(相当于使用JDBC打开一个数据库链接)
•InitialDirContext(Hashtable<?,?> environment)

绑定/创建LDAP条目对象(相当于新增一个LDAP条目数据bind(Name
•name, Object obj, Attributes attrs)
•bind(String name, Object obj, Attributes attrs)
•createSubcontext(Name name, Attributes attrs)
•createSubcontext(String name, Attributes attrs)

获取条目实例(属性集)

•getAttributes(Name name)
•getAttributes(Name name, String[] attrIds)
•getAttributes(String name)
•getAttributes(String name, String[] attrIds)

修改条目属性

•modifyAttributes(Name name, int mod_op, Attributes attrs)
•modifyAttributes(Name name, ModificationItem[] mods)
•modifyAttributes(String name, int mod_op, Attributes attrs)
•modifyAttributes(String name, ModificationItem[] mods)

删除条目

•destroySubcontext(Name name)
•destroySubcontext(String name)

根据属性集搜索条目

•search(Name name, Attributes matchingAttributes)
•search(Name name, Attributes matchingAttributes, String[] attributesToReturn)
•search(String name, Attributes matchingAttributes)
•search(String name, Attributes matchingAttributes, String[] attributesToReturn)

根据过滤器搜索条目

•search(Name name, String filterExpr, Object[] filterArgs, SearchControls cons)
•search(Name name, String filter, SearchControls cons)
•search(String name, String filterExpr, Object[] filterArgs, SearchControls cons)
•search(String name, String filter, SearchControls cons)


javax.naming.directory.BasicAttribute,LDAP基本属性对象
该类用来表示LDAP条目中的单个属性对象。在目录服务中,每个属性名称是可以对应多个的属性值的。

构建属性对象

•BasicAttribute(String id)
•BasicAttribute(String id, boolean ordered)
•BasicAttribute(String id, Object value)
•BasicAttribute(String id, Object value, boolean ordered)

添加属性值

•add(int ix, Object attrVal),添加属性值到多值属性的指定位置
•add(Object attrVal) , 追加属性值到多值属性尾部

判断属性值是否包含

•contains(Object attrVal) , 多值属性中有一个值是匹配的,返回true

获取属性值

•get(),取得属性值中的一个
•get(int ix),从多值属性中的指定位置取值

获取属性ID

•getID(),属性的ID就是属性名

删除属性值

•remove(int ix),删除指定位置的属性值
•remove(Object attrval),删除指定的属性值


javax.naming.directory.BasicAttributes,LDAP实体的属性集
该类表示一个LDAP条目绑定的属性集合,在绝大多数情况下,一个LDAP条目存在多个属性。

构造属性集

•BasicAttributes()
•BasicAttributes(boolean ignoreCase),属性ID是否大小写敏感,建议不要使用敏感
•BasicAttributes(String attrID, Object val)
•BasicAttributes(String attrID, Object val, boolean ignoreCase)

获取属性集中的单个属性对象

•get(String attrID)

获取全部属性的枚举

•getAll()

获取全部属性的ID枚举

•getIDs()

添加新属性

•put(Attribute attr)
•put(String attrID, Object val)

移除指定属性

•remove(String attrID)


javax.naming.directory.SearchControls , LDAP目录服务搜索控制对象
该类负责控制LDAP搜索行为的范围、设定返回结果数上限,搜索耗时上限,指定结果所包括的属性集等。

设定搜索行为的范围

•setSearchScope(int scope)

设定返回结果数上限

•setCountLimit(long limit)

设定搜索耗时上限

•setTimeLimit(int ms) , 以毫秒为单位

指定结果所包括的属性集

•setReturningAttributes(String[] attrs)


javax.naming.directory.SearchResult , 表示.search() 方法的返回结果集中的一项。
SearchResult类是对LDAP条目属性集的封装。在search()操作中可能返回完整的条目属性,也可能是条目属性的一部分。

获取SearchResult封装的条目属性

•getAttributes()




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值