JAVA_基本LDAP操作

一、LDAP概念

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

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

 

二、Softerra LDAP Administrator

         下载安装软件,并配置LDAP

  JAVA_基本LDAP操作                              

 

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

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

OU:Organization Unit 组织单元

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

 

三、在JAVA中应用LDAP

         1、配置文件

         <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

                   <property name="dataSource" ref="dataSource"/>

         </bean>

         <bean id="ldapcontextSource" class="org.springframework.ldap.core.support.LdapContextSource">

                   <property name="url" value="${LdapConnHost}" /> <!—例: LdapConnHost=ldap://10.190.123.123 -->

                   <property name="userDn" value="${LdapConnUser}" /><!—例: LdapConnUser=cn=root -->

                   <property name="password" value="${LdapConnPwd}" /><!—例: LdapConnPwd=111111 -->

                   <property name="base" value="${LdapBaseDn}" /> <!—Base DN 例: LdapBaseDn=DC=FJTIC -->

                   <property name="pooled" value="false" />

         </bean>

 

        

         2、JAVA代码

  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 }
spring版
  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 }
普通实现(转载)

 

你可能感兴趣的:(java)