`
cgs1999
  • 浏览: 530367 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用Java操作LDAP案例

阅读更多
1 案例描述
公司平台使用LDAP来储存企业或用户的信息,在系统的运行过程中需要对LDAP存储的信息进行相关的访问和操作,那么在Java中是如何操作LDAP的呢?

2 案例分析
LDAP是一个得到关于人或者资源的集中、静态数据的快速方式,是一种存储模式和访问协议。
UnboundID LDAP SDK for Java是一个快速、综合易用的 LDAP 目录服务的 Java 客户端API,它提供了一套快速、强大、用户友好并且开源的Java API来与LDAP目录服务器交互,可读写 LDIF、使用BASE64 和 ASN.1 BER 进行编码解码,支持安全通信等特性,要求 Java 1.5 或者更新版本支持,同时也支持 Android 平台。与其它基于Java的LDAP APIs相比,它具有更好的性能、更易于使用,功能更多,而且还是唯一一个不断有活跃开发和增强的SDK。
在软件开发中,对数据的操作无非就是增加、删除、修改、查询等4种操作,对LDAP的操作也一样。下面我们一起探讨在Java中如何使用UnboundID LDAP SDK操作LDAP。

3 解决过程
3.1 准备
1、Java客户端API(UnboundID LDAP SDK for Java)
下载地址 http://sourceforge.net/projects/ldap-sdk/files/

2、LDAP客户端(Apache Directory Studio)
下载地址 http://directory.apache.org/studio/

3.2 定义参数
// 当前配置信息
private static String ldapHost = "172.16.160.196";
private static int ldapPort = 389;
private static String ldapBindDN = "cn=manager,dc=com";;
private static String ldapPassword = "******";
private static LDAPConnection connection = null;

3.3 建立连接
/** 连接LDAP */
public static void openConnection() {
	if (connection == null) {
		try {
			connection = new LDAPConnection(ldapHost, ldapPort, ldapBindDN, ldapPassword);
		} catch (Exception e) {
			System.out.println("连接LDAP出现错误:\n" + e.getMessage());
		}
	}
}

3.4 创建数据
1、创建DC对象
/** 创建DC */
public static void createDC(String baseDN, String dc) {
	String entryDN = "dc=" + dc + "," + baseDN;
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(entryDN);
		if (entry == null) {
			// 不存在则创建
			ArrayList<Attribute> attributes = new ArrayList<Attribute>();
			attributes.add(new Attribute("objectClass", "top", "organization", "dcObject"));
			attributes.add(new Attribute("dc", dc));
			attributes.add(new Attribute("o", dc));
			connection.add(entryDN, attributes);
			System.out.println("创建DC" + entryDN + "成功!");
		} else {
			System.out.println("DC " + entryDN + "已存在!");
		}
	} catch (Exception e) {
		System.out.println("创建DC出现错误:\n" + e.getMessage());
	}
}

2、创建组织
/** 创建组织 */
public static void createO(String baseDN, String o) {
	String entryDN = "o=" + o + "," + baseDN;
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(entryDN);
		if (entry == null) {
			// 不存在则创建
			ArrayList<Attribute> attributes = new ArrayList<Attribute>();
			attributes.add(new Attribute("objectClass", "top", "organization"));
			attributes.add(new Attribute("o", o));
			connection.add(entryDN, attributes);
			System.out.println("创建组织" + entryDN + "成功!");
		} else {
			System.out.println("组织" + entryDN + "已存在!");
		}
	} catch (Exception e) {
		System.out.println("创建组织出现错误:\n" + e.getMessage());
	}
}

3、创建组织单元
/** 创建组织单元 */
public static void createOU(String baseDN, String ou) {
	String entryDN = "ou=" + ou + "," + baseDN;
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(entryDN);
		if (entry == null) {
			// 不存在则创建
			ArrayList<Attribute> attributes = new ArrayList<Attribute>();
			attributes.add(new Attribute("objectClass", "top", "organizationalUnit"));
			attributes.add(new Attribute("ou", ou));
			connection.add(entryDN, attributes);
			System.out.println("创建组织单元" + entryDN + "成功!");
		} else {
			System.out.println("组织单元" + entryDN + "已存在!");
		}
	} catch (Exception e) {
			System.out.println("创建组织单元出现错误:\n" + e.getMessage());
	}
}

4、创建用户
/** 创建用户 */
public static void createEntry(String baseDN, String uid) {
	String entryDN = "uid=" + uid + "," + baseDN;
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(entryDN);
		if (entry == null) {
			// 不存在则创建
			ArrayList<Attribute> attributes = new ArrayList<Attribute>();
			attributes.add(new Attribute("objectClass", "top", "account"));
			attributes.add(new Attribute("uid", uid));
			connection.add(entryDN, attributes);
			System.out.println("创建用户" + entryDN + "成功!");
		} else {
			System.out.println("用户" + entryDN + "已存在!");
		}
	} catch (Exception e) {
		System.out.println("创建用户出现错误:\n" + e.getMessage());
	}
}

3.5 修改数据
/** 修改用户信息 */
public static void modifyEntry(String requestDN, Map<String,String> data) {
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(requestDN);
		if (entry == null) {
			System.out.println(requestDN + " user:" + requestDN + " 不存在);
			return;
		}
		// 修改信息
		ArrayList<Modification> md = new ArrayList<Modification>();
		for(String key : data.keySet()) {
			md.add(new Modification(ModificationType.REPLACE, key, data.get(key)));
		}
		connection.modify(requestDN, md);

		System.out.println("修改用户信息成!");
	} catch (Exception e) {
		System.out.println("修改用户信息出现错误:\n" + e.getMessage());
	}
}

3.6 删除数据
/** 删除用户信息 */
public static void deleteEntry(String requestDN) {
	try {
		// 连接LDAP
		openConnection();
		
		SearchResultEntry entry = connection.getEntry(requestDN);
		if (entry == null) {
			System.out.println(requestDN + " user:" + requestDN + "不存在");
			return;
		}
		// 删除
		connection.delete(requestDN);
		System.out.println("删除用户信息成!");
	} catch (Exception e) {
		System.out.println("删除用户信息出现错误:\n" + e.getMessage());
	}
}

3.7 查询数据
/** 查询 */
public static void queryLdap(String searchDN, String filter) {
	try {
		// 连接LDAP
		openConnection();
		
		// 查询企业所有用户
		SearchRequest searchRequest = new SearchRequest(searchDN, SearchScope.SUB, "(" + filter + ")");
		searchRequest.addControl(new SubentriesRequestControl());
		SearchResult searchResult = connection.search(searchRequest);
		System.out.println(">>>共查询到" + searchResult.getSearchEntries().size() + "条记录");
		int index = 1;
		for (SearchResultEntry entry : searchResult.getSearchEntries()) {
			System.out.println((index++) + "\t" + entry.getDN());
		}
	} catch (Exception e) {
		System.out.println("查询错误,错误信息如下:\n" + e.getMessage());
	}
}

3.8 测试代码
public static void main(String[] args) {
	String root = "com";
	String dc = "truesens";
	String o = "kedacom";
	String ou = "people";
	String uid = "admin";
	String filter = "objectClass=account";

	createDC("dc=" + root, dc);
	createO("dc=" + dc + ",dc=" + root, o);
	createOU("o=" + o + ",dc=" + dc + ",dc=" + root, ou);
	createEntry("ou=" + ou + ",o=" + o + ",dc=" + dc + ",dc=" + root, uid);
	queryLdap("ou=" + ou + ",o=" + o + ",dc=" + dc + ",dc=" + root, filter);
	
	HashMap<String,String> data = new HashMap<String,String>(0);
	data.put("userid", uid);
modifyEntry("uid="+uid+",ou="+ou+",o="+o+",dc="+dc+",dc="+root, data);
	
	deleteEntry("uid="+uid+",ou="+ou + ",o="+o+",dc=" + dc + ",dc=" + root);
	queryLdap("ou=" + ou + ",o=" + o + ",dc=" + dc + ",dc=" + root, filter);
}


4 解决结果
1、输出结果
创建代理商dc=truesens,dc=com成功!
创建组织o=kedacom,dc=truesens,dc=com成功!
创建组织单元ou=people,o=kedacom,dc=truesens,dc=com成功!
创建用户uid=admin,ou=people,o=kedacom,dc=truesens,dc=com成功!
>>>共查询到1条记录
1	uid=admin,ou=people,o=kedacom,dc=truesens,dc=com
修改用户信息成功!
删除用户信息成功!
>>>共查询到0条记录


2、使用LDAP客户端Apache Directory Studio连接LDAP服务查看LDAP数据,如下图所示


5 总结
从解决过程和解决结果,我们可知在Java中使用UnboundID LDAP SDK for Java所提供的API来操作LDAP,实现对LDAP数据进行增加、修改、删除、查询都很简单和易用。

6 源代码
完整测试代码请查看下面附件
完整代码点击这里下载
  • 大小: 25.8 KB
分享到:
评论
31 楼 cgs1999 2018-04-23  
845896876 写道
老师你好,我发现// 自定义属性 
            attributes.add(new Attribute("enable", enable));
其中的enable这个属性是没有定义的,

给我报错也是属性未定义,请问这个属性是在哪定义的,我的Q是845896876,如果不忙的话可以麻烦您一下么?


由于可以参考一下11楼,自定义属性都是新建的时候加上去的
30 楼 845896876 2018-03-01  
老师你好,我发现// 自定义属性 
            attributes.add(new Attribute("enable", enable));
其中的enable这个属性是没有定义的,

给我报错也是属性未定义,请问这个属性是在哪定义的,我的Q是845896876,如果不忙的话可以麻烦您一下么?
29 楼 cgs1999 2017-09-28  
有网友来信问说unboundid-ldapsdk使用的是什么版本?

本文是2012年写的,当时使用的是unboundid-ldapsdk-2.2.0.jar,最新版本已是4.0.1了,可到http://sourceforge.net/projects/ldap-sdk/files/ 去下载,不过由于版本的问题,可能最新的API已有调整,本文的代码可能在新版本中存在问题,若要使用新版本的网友,请自行查阅相关文档进行调整
28 楼 cgs1999 2014-10-31  
cey009008 写道
请教一下:查询的时候,怎么可以查到一个用户的字段并将其取出来,比如我想查询userPassword字段,希望有知道的游客也可以帮忙回答一下

补充下:就是怎么查到一个用户的所有属性值并获取到


实际上查一下API文档就可以解决你的问题了,参考API文档
http://grepcode.com/file/repo1.maven.org/maven2/com.unboundid/unboundid-ldapsdk/2.3.0/com/unboundid/ldap/sdk/SearchResultEntry.java
http://grepcode.com/file/repo1.maven.org/maven2/com.unboundid/unboundid-ldapsdk/2.3.0/com/unboundid/ldap/sdk/Attribute.java


改造3.7中的查询代码(注:以下代码未经测试)
-------------------------------------------
/** 查询 */
public static void queryLdap(String searchDN, String filter) {
try {
...(略)
for (SearchResultEntry entry : searchResult.getSearchEntries()) {
System.out.println((index++) + "\t" + entry.getDN());

// 获取各字段的值
Collection<Attribute> attributes = entry.getAttributes();
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + "=" + attribute.getValue());
}

// 获取指定字段的值
if (entry.hasAttribute("userName")) {
System.out.println("userName=" + entry.getAttributeValue("userName"));
}
}
} catch (Exception e) {
System.out.println("查询错误,错误信息如下:\n" + e.getMessage());
}
}
27 楼 cey009008 2014-10-29  
补充下:就是怎么查到一个用户的所有属性值并获取到
26 楼 cey009008 2014-10-29  
请教一下:查询的时候,怎么可以查到一个用户的字段并将其取出来,比如我想查询userPassword字段,希望有知道的游客也可以帮忙回答一下
25 楼 cgs1999 2014-05-28  
路人甲wxf 写道
这个修改LDAP中的密码的话不需要导入证书吗?


在openldap中修改LDAP的连接密码,或修改数据中的密码都不需要导入证书
24 楼 路人甲wxf 2014-05-28  
这个修改LDAP中的密码的话不需要导入证书吗?
23 楼 cgs1999 2014-05-22  
路人甲wxf 写道
我指的是修改LDAP中用户的密码


修改的是LDAP数据,可以直接使用“3.5 修改数据”的方法直接处理,只要将要修改的相关的参数传入即可,参考代码如下:

String requestDN = "uid=admin,ou=people,o=kedacom,dc=truesens,dc=com";
Map<String,String> data = new HashMap<String,String> (0);
data.put("password", "12345678");

modifyEntry(requestDN, data);
22 楼 路人甲wxf 2014-05-22  
我指的是修改LDAP中用户的密码
21 楼 cgs1999 2014-05-21  
路人甲wxf 写道
能说一下怎么修改密码吗??


你是指修改LDAP的密码吗?

我们使用的是openldap,ldap的密码是在安装的时候通过openldap的配置文件slapd.conf设定的,有个配置项rootpw,修改该值就可以了
20 楼 cgs1999 2014-05-21  
Just1n 写道
官网上找到的示例代码,跟楼主这里的不一样。
请问楼主这个是在哪看到的?


不好意思,之前没及时回复,后来给忘了

这个代码是我们之前参考官网的代码,并根据自己的业务开发的代码,同上述类似的代码已在公司的系统中运行
19 楼 路人甲wxf 2014-05-21  
能说一下怎么修改密码吗??
18 楼 Just1n 2014-01-22  
官网上找到的示例代码,跟楼主这里的不一样。
请问楼主这个是在哪看到的?
17 楼 cgs1999 2013-05-01  
Spring_g 写道
楼主 在服务端排序和分页是怎样实现的


排序和分页的处理都是在服务端搜索出所有的数据然后再进行排序或分页的,效率比较低。

现项目由于种种原因(包含由于效率的问题),已不再使用LDAP而改用mysql+memcache方式来实现原有的功能


对于LDAP分页和排序可参考
http://www.doc88.com/p-952216768436.html
16 楼 Spring_g 2013-04-28  
楼主 在服务端排序和分页是怎样实现的
15 楼 cgs1999 2013-04-22  
Spring_g 写道
cgs1999 写道
如前面所提供的范例代码,自定义属性直接加相关的代码即可。

若是自定义objectClass类型,目前我们使用的是创建schema文件的方式在启动时加载,至于动态生成没有使用过~~
我在这边测试的创建自定义的属性 是不能直接添加的,必须添加指定objectclass里配置好的属性,不知道是代码问题 还是版本问题


这个问题没有遇到过,你的问题估计是环境的问题,需结合环境进行排查。

我理解的LDAP中Entry就是一组key-value形成的数据,可以根据需要扩展不同的属性,且不同的Entry的属性也可以不尽相同。
14 楼 Spring_g 2013-04-22  
cgs1999 写道
如前面所提供的范例代码,自定义属性直接加相关的代码即可。

若是自定义objectClass类型,目前我们使用的是创建schema文件的方式在启动时加载,至于动态生成没有使用过~~
我在这边测试的创建自定义的属性 是不能直接添加的,必须添加指定objectclass里配置好的属性,不知道是代码问题 还是版本问题
13 楼 cgs1999 2013-04-22  
Spring_g 写道
要是自定义属性 是不是要写个schema文件在服务启动时加载进去  还是可以动态的生成那?


如前面所提供的范例代码,自定义属性直接加相关的代码即可。

若是自定义objectClass类型,目前我们使用的是创建schema文件的方式在启动时加载,至于动态生成没有使用过~~
12 楼 Spring_g 2013-04-18  
要是自定义属性 是不是要写个schema文件在服务启动时加载进去  还是可以动态的生成那?

相关推荐

    LDAP代码操作 Demo

    LDAP代码操作Demo,LDAP操作代码样例 初始化LDAP 目录服务上下文、绑定/创建LDAP条目对象、获取条目属性、修改条目属性等实例

    Java数据编程指南

    Java和ODMG 3.0规范 基础 ODMG的核心概念 对象定义语言 小结 第11章 目录服务与JNDI 命名与目录服务 使用JNDI JAVA与LDAP 从理论到实践 标准的LDAP操作 LDAP服务器改进 在LDAP...

    JSP编程指南(pdf)

    更通过大量的案例分析对如何使用JSP、XML和XSLT在WAP浏览器和HTML浏览器中显示web内容、使用LDAP开发电子商务以及使用JMF处理数据等进行了详尽的阐述, 对于那些想要将JSP作为其J2EE平台上Web应用前端的专业Java软件...

    iBATIS实战

    11.2.1 示例:为LDAP使用DAO 203 11.2.2 示例:为Web服务使用DAO 208 11.3 使用Spring DAO 209 11.3.1 编写代码 209 11.3.2 为什么使用Spring代替iBATIS 211 11.4 创建自己的DAO层 211 11.4.1 从实现中分离出接口 ...

    从无到有搭建中小型互联网公司后台服务架构与运维架构

    课程将会通过实际案例讲解,并且会提供完整的视频案例源码供学员学习使用,同时有需要的企业或学员可以直接拿本套教学案例代码来使用或者二次开发。 本课程设计的技术及工具如下: 后台服务架构:dubbo、spring-...

    czerocase-logging:框架 CZeroCase 的“日志记录”模块

    Czero 框架基于 Java 环境,集成了 OSGI、CMIS、WSS、LDAP 等最现代的解决方案,使设计人员和开发人员能够以简单直观的方式构建文档和流程管理的创新解决方案。 基于模式的方法将涉及对使用模块化和可扩展性方法...

    czerocase-logging-listener-console:框架 CZeroCase 的“日志控制台”模块

    Czero 框架基于 Java 环境,集成了 OSGI、CMIS、WSS、LDAP 等最现代的解决方案,使设计人员和开发人员能够以简单直观的方式构建文档和流程管理的创新解决方案。 基于模式的方法将涉及对使用模块化和可扩展性方法...

    czerocase-test-modules:框架 CZeroCase 的“测试”模块

    Czero 框架基于 Java 环境,集成了 OSGI、CMIS、WSS、LDAP 等最现代的解决方案,使设计人员和开发人员能够以简单直观的方式构建文档和流程管理的创新解决方案。 基于模式的方法将涉及对使用模块化和可扩展性方法...

    CzeroCase:案件管理框架-开源

    基于Java环境的Czero框架集成了OSGI,CMIS,WSS,LDAP等最现代的解决方案,使设计人员和开发人员可以轻松,直观地构建用于文档和流程管理的创新解决方案。 基于模式的方法将吸引广泛的社区,他们有兴趣使用模块化和...

    MaxKey单点登录认证系统-其他

    7、基于Java平台开发,采用Spring、MySQL、Tomcat、Apache Kafka、Redis等开源技术,支持微服务,扩展性强。 8、许可证 Apache License, Version 2.0,开源免费。     MaxKey单点登录认证系统 更新日志: v2.7.0 ...

Global site tag (gtag.js) - Google Analytics