新疆都市报 > 科技 > 智能 >

JAVA操作LDAP总结

发布时间:2019-04-12 10:33来源: 未知


一、LDAP概念

LDAP的全称为Lightweight Directory Access Protocol(轻量级目录访问协议), 基于X.500标准, 支持 TCP/IP。

LDAP目录为数据库,通过LDAP服务器(相当于DBMS)处理查询和更新, 以树状的层次结构来存储数据,相对关系型数据库, LDAP主要是优化数据读取的性能,适用于比较少改变、跨平台的信息。

二、Softerra LDAP Administrator

下载安装软件,并配置LDAP

DN:Distinguished Name 唯一标识一条记录的路径,Base DN为基准DN,指定LDAP search的起始DN,即从哪个DN下开始搜索,RDN为叶子结点本身的名字。

DC:Domain Component 一条记录所属区域

OU:Organization Unit 组织单元

CN/UID:一条记录的名字/ID

三、在JAVA中应用LDAP

1、spring配置文件

四、JAVA代码

4.1spring版本 1 package com.test.dao;

2

3 import java.beans.PropertyDescriptor;

4 import java.lang.reflect.Field;

5 import java.lang.reflect.InvocationTargetException;

6 import java.lang.reflect.Method;

7 import java.util.ArrayList;

8 import java.util.List;

9 import javax.naming.Name;

10 import javax.naming.NamingEnumeration;

11 import javax.naming.NamingException;

12 import javax.naming.directory.Attribute;

13 import javax.naming.directory.Attributes;

14 import javax.naming.directory.BasicAttribute;

15 import javax.naming.directory.BasicAttributes;

16 import javax.naming.directory.ModificationItem;

17 import org.apache.commons.beanutils.BeanUtils;

18 import org.springframework.beans.factory.annotation.Autowired;

19 import org.springframework.dao.EmptyResultDataAccessException;

20 import org.springframework.ldap.core.ContextMapper;

21 import org.springframework.ldap.core.DirContextAdapter;

22 import org.springframework.ldap.core.DirContextOperations;

23 import org.springframework.ldap.core.DistinguishedName;

24 import org.springframework.ldap.core.LdapTemplate;

25 import org.springframework.ldap.core.support.AbstractContextMapper;

26 import org.springframework.ldap.filter.AndFilter;

27 import org.springframework.ldap.filter.EqualsFilter;

28 import org.springframework.ldap.filter.OrFilter;

29 import org.springframework.stereotype.Component;

30 import com.surekam.model.Person;

31 import com.surekam.utils.DateCl;

32 import com.surekam.utils.StringUtil;

33

34 @Component

35 public class UserDAOL {

36 @Autowired

37 private LdapTemplate ldapTemplate;

38

39 /**

40 *

41 * @Description: 添加

42 *

43 */

44 public boolean addPerson(Person person) {

45 boolean flag = false;

46 Name dn = buildUDn(person.getUid());

47 Attributes buildAddAttributes = buildAddAttributes(person);

48 ldapTemplate.bind(dn, null, buildAddAttributes);

49 flag = true;

50 return flag;

51 }

52

53 /**

54 *

55 * @Description: 修改

56 *

57 */

58 public boolean updatePerson(Person person) {

59 boolean flag = false;

60 Name dn = buildUDn(person.getUid());

61 ModificationItem[] modificationItem = buildModifyAttributes(person);

62 ldapTemplate.modifyAttributes(dn, modificationItem);

63 flag = true;

64 return flag;

65 }

66

67 /**

68 *

69 * 多条件获取用户

70 *

71 */

72 public List<Person> getPersonByOu(String ou, String level) {

73 AndFilter filter = new AndFilter();

74 OrFilter orFilter1 = new OrFilter();

75 if ("处级干部".equals(level)) {

76 orFilter1.or(new EqualsFilter("cuadministrativelevels", "aa"));

77 orFilter1.or(new EqualsFilter("cuadministrativelevels", "bb"));

78 orFilter1.or(new EqualsFilter("cuadministrativelevels", "cc"));

79 orFilter1.or(new EqualsFilter("cuadministrativelevels", "dd"));

80 }

81 if ("普通员工".equals(level)) {

82 orFilter1.or(new EqualsFilter("cuadministrativelevels", "ee"));

83 orFilter1.or(new EqualsFilter("cuadministrativelevels", "ff"));

84 orFilter1.or(new EqualsFilter("cuadministrativelevels", "gg"));

85 }

86 OrFilter orFilter2 = new OrFilter();

87 orFilter2.or(new EqualsFilter("departmentnumber", ou));

88 orFilter2.or(new EqualsFilter("cutransferdnumber", ou));

89 filter.and(orFilter2);

90 filter.and(orFilter1);

91 System.out.println(filter.toString());

92 List<Person> list = ldapTemplate.search("cn=users,dc=hq", filter

93 .encode(), new PersonContextMapper());

94 return list;

95 }

96

97

98 /**

99 *

100 * 生成用户DN

101 *

102 * @return uid=123455,cn=users,dc=hq

103 */

104 private Name buildUDn(String urdn) {

105 DistinguishedName dn = new DistinguishedName("");

106 dn.add("dc", "hq");

107 dn.add("cn", "users");

108 dn.add("uid", urdn);

109 return dn;

110 }

111

112 /**

113 *

114 * 组织查询结果

115 *

116 */

117 public static class PersonContextMapper implements ContextMapper {

118 public Object mapFromContext(Object ctx) {

119 if (ctx == null)

120 return new Person();

121 DirContextAdapter context = (DirContextAdapter) ctx;

122 Person per = new Person();

123 Attributes attrs = context.getAttributes();

124 NamingEnumeration results = attrs.getAll();

125 Class c = per.getClass();

126 while (results.hasMoreElements()) {

127 try {

128 Attribute attr = (Attribute) results.next();

129 String value = attr.get().toString();

130 if (StringUtil.isNotEmpty(value)) {

131 String fieldName = attr.getID();

132 if ("objectclass".equals(fieldName.toLowerCase())) {

133 continue;

134 }

135 Field field = c.getDeclaredField(fieldName

136 .toLowerCase());

137 Class fieldClazz = field.getType();

138 /*

139 * 如果属性条数大于1,那就是多值属性 attr.getAttributeDefinition()

140 * 获取多值属性的方法没找到

141 */

142 if (fieldClazz.isAssignableFrom(List.class)) { // 属性值数大于1

143 NamingEnumeration values = attr.getAll(); // 获取所有值

144 // LDAP中的多值属性只会是String类型

145 List<String> list = new ArrayList<String>();

146 while (values.hasMoreElements()) {

147 list.add(values.next().toString());

148 }

149 BeanUtils.setProperty(per, fieldName.toLowerCase(),

150 list);

151 } else {

152 // 普通属性

153 BeanUtils.setProperty(per, fieldName.toLowerCase(),

154 value);

155 }

156 }

157 } catch (IllegalAccessException e) {

158 e.printStackTrace();

159 } catch (InvocationTargetException e) {

160 e.printStackTrace();

161 } catch (NamingException e) {

162 e.printStackTrace();

163 } catch (SecurityException e) {

164 // TODO Auto-generated catch block

165 e.printStackTrace();

166 } catch (NoSuchFieldException e) {

167 // TODO Auto-generated catch block

168 e.printStackTrace();

169 }

170 }

171 per.setDn(context.getNameInNamespace());

172 return per;

173 }

174 }

175

176 /**

177 *

178 * 组织添加数据数据

179 *

180 */

181 @SuppressWarnings("unchecked")

182 private Attributes buildAddAttributes(Person p) {

183 Attributes attrs = new BasicAttributes();

184 BasicAttribute ocattr = new BasicAttribute("objectclass");

185 ocattr.add("top");

186 ocattr.add("person");

187 ocattr.add("organizationalPerson");

188 ocattr.add("inetOrgPerson");

189 ocattr.add("FJTicPerson");

190 attrs.put(ocattr);

191 Class c = p.getClass();

192 Field[] fields = c.getDeclaredFields();

193 for (int i = 0; i < fields.length; i++) {

194 try {

195 Class fieldClazz = fields[i].getType();

196 String fieldName = fields[i].getName(); // 获得属性名

197 String fieldVlue = BeanUtils.getProperty(p, fieldName); // 获得属性值

198 /*

199 * 判断属性是否要过滤,例如修改时间之类的字段LDAP是没有的 判断属性值是否为空,在这里过滤了所有null和""

200 * 增加操作中不存在主动设置某个值为空的情况 所以只需要处理有值属性

201 */

202 if (checkfieldName(fieldName) || StringUtil.isEmpty(fieldVlue))

203 continue;

204 /*

205 * 多值属性的处理 如果多值属性为空,那么增加的时候就不会增加值进去

206 */

207 if (fieldClazz.isAssignableFrom(List.class)) { // 集合属性

208 BasicAttribute ocattr1 = new BasicAttribute(fieldName);

209 PropertyDescriptor pd = new PropertyDescriptor(fieldName, c);

210 Method getMethod = pd.getReadMethod();// 获得get方法

211 List list = (List) getMethod.invoke(p);// 执行get方法返回一个Object

212 for (Object object : list) {

213 ocattr1.add(object);

214 }

215 attrs.put(ocattr1);

216 } else {

217 attrs.put(fieldName, fieldVlue);

218 }

219 } catch (Exception e) {

220 e.printStackTrace();

221 }

222 }

223 return attrs;

224

225 }

226

227 /**

228 *

229 * 组织修改数据

230 *

231 */

232 @SuppressWarnings("unchecked")

233 private ModificationItem[] buildModifyAttributes(Person p) {

234 ArrayList<ModificationItem> attrs = new ArrayList<ModificationItem>();

235 Class c = p.getClass();

236 Field[] fields = c.getDeclaredFields();

237 for (Field field : fields) {

238 try {

239 Class fieldClazz = field.getType();

240 String fieldName = field.getName(); // 获得属性名

241 String fieldValue = BeanUtils.getProperty(p, fieldName);

242 /*

243 * 判断属性是否要过滤,例如修改时间之类的字段LDAP是没有的 判断属性值是否为空,在这里过滤了所有null和""

244 * 要置空的属性通过识别特殊属性值:delAtr 在后面做重新置空操作

245 */

246 if (checkfieldName(fieldName) || StringUtil.isEmpty(fieldValue))

247 continue;

248 BasicAttribute basicAttr = new BasicAttribute(fieldName);

249 /*

250 * 多值属性的处理 如果传递一个空的list,那么修改的时候就会清空多值属性 (new ArrayList<String>())

251 */

252 if (fieldClazz.isAssignableFrom(List.class)) { // 如果是集合属性

253 PropertyDescriptor pd = new PropertyDescriptor(fieldName, c);

254 Method getMethod = pd.getReadMethod();// 获得get方法

255 List list = (List) getMethod.invoke(p);// 执行get方法返回一个Object

256 for (Object object : list) {

257 basicAttr.add(object);

258 }

259 } else {

260 /*

261 * 判断删除标记来对值进行置空 传递过来的对象中有些属性没有做修改就传递了"" 有些是要修改为 ""

262 * 所以在上面要过滤所有 "" 属性,避免将不修改的参数全都置空了 然后通过识别要修改参数的特有值来判断是否主动置空

263 * 如果add一个""进去,那么在LDAP中依然会显示

264 * 如果不给值,由BasicAttribute自动授予空值,那么在LDAP中就不显示了

265 */

266 if ("delAtr".equals(fieldValue)) {

267 basicAttr.add(""); // 置空属性

268 } else {

269 basicAttr.add(fieldValue);// 有值属性

270 }

271 }

272 // 替换条目

273 attrs.add(new ModificationItem(

274 DirContextAdapter.REPLACE_ATTRIBUTE, basicAttr));

275 } catch (Exception e) {

276 e.printStackTrace();

277 }

278 }

279 return attrs.toArray(new ModificationItem[attrs.size()]);

280 }

281

282 /**

283 *

284 * 过滤默认值字段

285 *

286 */

287 private static boolean checkfieldName(String fieldName) {

288 String[] check = new String[] { "id", "status", "createtime",

289 "updatetime", "dn" };

290 for (int i = 0; i < check.length; i++) {

291 if (check[i].equalsIgnoreCase(fieldName))

292 return true;

293 }

294 return false;

295 }

296 }

4.2普通实现1 package com.smnpc.util;

2

3 import java.util.Hashtable;

4 import java.util.Vector;

5

6 import javax.naming.Context;

7 import javax.naming.NamingEnumeration;

8 import javax.naming.NamingException;

9 import javax.naming.directory.Attribute;

10 import javax.naming.directory.Attributes;

11 import javax.naming.directory.BasicAttribute;

12 import javax.naming.directory.BasicAttributes;

13 import javax.naming.directory.DirContext;

14 import javax.naming.directory.InitialDirContext;

15 import javax.naming.directory.ModificationItem;

16 import javax.naming.directory.SearchControls;

17 import javax.naming.directory.SearchResult;

18 import javax.naming.ldap.LdapContext;

19

20 /**

21 * Java通过Ldap操作AD的增删该查询

22 *

23 * @author guob

24 */

25

26 public class LdapbyUser {

27 DirContext dc = null;

28 String root = "dc=example,dc=com"; // LDAP的根节点的DC

29

30 /**

31 *

32 * @param dn类似于"CN=RyanHanson,dc=example,dc=com"

33 * @param employeeID是Ad的一个员工号属性

34 */

35 public LdapbyUser(String dn, String employeeID) {

36 init();

37 // add();//添加节点

38 // delete("ou=hi,dc=example,dc=com");//删除"ou=hi,dc=example,dc=com"节点

39 // renameEntry("ou=new,o=neworganization,dc=example,dc=com","ou=neworganizationalUnit,o=neworganization,dc=example,dc=com");//重命名节点"ou=new,o=neworganization,dc=example,dc=com"

40 // searchInformation("dc=example,dc=com", "",

41 // "sAMAccountName=guob");//遍历所有根节点

42 modifyInformation(dn, employeeID);// 修改

43 // Ldapbyuserinfo("guob");//遍历指定节点的分节点

44 close();

45 }

46

47 /**

48 *

49 * Ldap连接

50 *

51 * @return LdapContext

52 */

53 public void init() {

54 Hashtable env = new Hashtable();

55 String LDAP_URL = "ldap://xxxx:389"; // LDAP访问地址

56 String adminName = "example\\\user"; // 注意用户名的写法:domain\User或

57 String adminPassword = "userpassword"; // 密码

58 env.put(Context.INITIAL_CONTEXT_FACTORY,

59 "com.sun.jndi.ldap.LdapCtxFactory");

60 env.put(Context.PROVIDER_URL, LDAP_URL);

61 env.put(Context.SECURITY_AUTHENTICATION, "simple");

62 env.put(Context.SECURITY_PRINCIPAL, adminName);

63 env.put(Context.SECURITY_CREDENTIALS, adminPassword);

64 try {

65 dc = new InitialDirContext(env);// 初始化上下文

66 System.out.println("认证成功");// 这里可以改成异常抛出。

67 } catch (javax.naming.AuthenticationException e) {

68 System.out.println("认证失败");

69 } catch (Exception e) {

70 System.out.println("认证出错:" + e);

71 }

72 }

73

74 /**

75 * 添加

76 */

77 public void add(String newUserName) {

78 try {

79 BasicAttributes attrs = new BasicAttributes();

80 BasicAttribute objclassSet = new BasicAttribute("objectClass");

81 objclassSet.add("sAMAccountName");

82 objclassSet.add("employeeID");

83 attrs.put(objclassSet);

84 attrs.put("ou", newUserName);

85 dc.createSubcontext("ou=" + newUserName + "," + root, attrs);

86 } catch (Exception e) {

87 e.printStackTrace();

88 System.out.println("Exception in add():" + e);

89 }

90 }

91

92 /**

93 * 删除

94 *

95 * @param dn

96 */

97 public void delete(String dn) {

98 try {

99 dc.destroySubcontext(dn);

100 } catch (Exception e) {

101 e.printStackTrace();

102 System.out.println("Exception in delete():" + e);

103 }

104 }

105

106 /**

107 * 重命名节点

108 *

109 * @param oldDN

110 * @param newDN

111 * @return

112 */

113 public boolean renameEntry(String oldDN, String newDN) {

114 try {

115 dc.rename(oldDN, newDN);

116 return true;

117 } catch (NamingException ne) {

118 System.err.println("Error: " + ne.getMessage());

119 return false;

120 }

121 }

122

123 /**

124 * 修改

125 *

126 * @return

127 */

128 public boolean modifyInformation(String dn, String employeeID) {

129 try {

130 System.out.println("updating...\n");

131 ModificationItem[] mods = new ModificationItem[1];

132 /* 修改属性 */

133 // Attribute attr0 = new BasicAttribute("employeeID", "W20110972");

134 // mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,

135 // attr0);

136 /* 删除属性 */

137 // Attribute attr0 = new BasicAttribute("description",

138 // "陈轶");

139 // mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,

140 // attr0);

141 /* 添加属性 */

142 Attribute attr0 = new BasicAttribute("employeeID", employeeID);

143 mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);

144 /* 修改属性 */

145 dc.modifyAttributes(dn + ",dc=example,dc=com", mods);

146 return true;

147 } catch (NamingException e) {

148 e.printStackTrace();

149 System.err.println("Error: " + e.getMessage());

150 return false;

151 }

152 }

153

154 /**

155 * 关闭Ldap连接

156 */

157 public void close() {

158 if (dc != null) {

159 try {

160 dc.close();

161 } catch (NamingException e) {

162 System.out.println("NamingException in close():" + e);

163 }

164 }

165 }

166

167 /**

168 * @param base

169 * :根节点(在这里是"dc=example,dc=com")

170 * @param scope

171 * :搜索范围,分为"base"(本节点),"one"(单层),""(遍历)

172 * @param filter

173 * :指定子节点(格式为"(objectclass=*)",*是指全部,你也可以指定某一特定类型的树节点)

174 */

175 public void searchInformation(String base, String scope, String filter) {

176 SearchControls sc = new SearchControls();

177 if (scope.equals("base")) {

178 sc.setSearchScope(SearchControls.OBJECT_SCOPE);

179 } else if (scope.equals("one")) {

180 sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);

181 } else {

182 sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

183 }

184 NamingEnumeration ne = null;

185 try {

186 ne = dc.search(base, filter, sc);

187 // Use the NamingEnumeration object to cycle through

188 // the result set.

189 while (ne.hasMore()) {

190 System.out.println();

191 SearchResult sr = (SearchResult) ne.next();

192 String name = sr.getName();

193 if (base != null && !base.equals("")) {

194 System.out.println("entry: " + name + "," + base);

195 } else {

196 System.out.println("entry: " + name);

197 }

198

199 Attributes at = sr.getAttributes();

200 NamingEnumeration ane = at.getAll();

201 while (ane.hasMore()) {

202 Attribute attr = (Attribute) ane.next();

203 String attrType = attr.getID();

204 NamingEnumeration values = attr.getAll();

205 Vector vals = new Vector();

206 // Another NamingEnumeration object, this time

207 // to iterate through attribute values.

208 while (values.hasMore()) {

209 Object oneVal = values.nextElement();

210 if (oneVal instanceof String) {

211 System.out.println(attrType + ": "

212 + (String) oneVal);

213 } else {

214 System.out.println(attrType + ": "

215 + new String((byte[]) oneVal));

216 }

217 }

218 }

219 }

220 } catch (Exception nex) {

221 System.err.println("Error: " + nex.getMessage());

222 nex.printStackTrace();

223 }

224 }

225

226 /**

227 * 查询

228 *

229 * @throws NamingException

230 */

231 public void Ldapbyuserinfo(String userName) {

232 // Create the search controls

233 SearchControls searchCtls = new SearchControls();

234 // Specify the search scope

235 searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

236 // specify the LDAP search filter

237 String searchFilter = "sAMAccountName=" + userName;

238 // Specify the Base for the search 搜索域节点

239 String searchBase = "DC=example,DC=COM";

240 int totalResults = 0;

241 String returnedAtts[] = { "url", "whenChanged", "employeeID", "name",

242 "userPrincipalName", "physicalDeliveryOfficeName",

243 "departmentNumber", "telephoneNumber", "homePhone", "mobile",

244 "department", "sAMAccountName", "whenChanged", "mail" }; // 定制返回属性

245

246 searchCtls.setReturningAttributes(returnedAtts); // 设置返回属性集

247

248 // searchCtls.setReturningAttributes(null); // 不定制属性,将返回所有的属性集

249

250 try {

251 NamingEnumeration answer = dc.search(searchBase, searchFilter,

252 searchCtls);

253 if (answer == null || answer.equals(null)) {

254 System.out.println("answer is null");

255 } else {

256 System.out.println("answer not null");

257 }

258 while (answer.hasMoreElements()) {

259 SearchResult sr = (SearchResult) answer.next();

260 System.out

261 .println("************************************************");

262 System.out.println("getname=" + sr.getName());

263 Attributes Attrs = sr.getAttributes();

264 if (Attrs != null) {

265 try {

266

267 for (NamingEnumeration ne = Attrs.getAll(); ne

268 .hasMore();) {

269 Attribute Attr = (Attribute) ne.next();

270 System.out.println("AttributeID="

271 + Attr.getID().toString());

272 // 读取属性值

273 for (NamingEnumeration e = Attr.getAll(); e

274 .hasMore(); totalResults++) {

275 String user = e.next().toString(); // 接受循环遍历读取的userPrincipalName用户属性

276 System.out.println(user);

277 }

278 // System.out.println(" ---------------");

279 // // 读取属性值

280 // Enumeration values = Attr.getAll();

281 // if (values != null) { // 迭代

282 // while (values.hasMoreElements()) {

283 // System.out.println(" 2AttributeValues="

284 // + values.nextElement());

285 // }

286 // }

287 // System.out.println(" ---------------");

288 }

289 } catch (NamingException e) {

290 System.err.println("Throw Exception : " + e);

291 }

292 }

293 }

294 System.out.println("Number: " + totalResults);

295 } catch (Exception e) {

296 e.printStackTrace();

297 System.err.println("Throw Exception : " + e);

298 }

299 }

300

301 /**

302 * 主函数用于测试

303 *

304 * @param args

305 */

306 public static void main(String[] args) {

307 new LdapbyUser("CN=RyanHanson", "bbs.it-home.org");

308 }

309 }