Ldap Api

Java6.0 API for LDAP概述

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


常用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)

u
删除条目

  • 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)

u
根据过滤器搜索条目

  • 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()

u
添加新属性

  • put(Attribute attr)

  • put(String attrID, Object val)

u
移除指定属性

  • remove(String attrID)



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

设定搜索行为的范围

  • setSearchScope(int scope)

u
设定返回结果数上限

  • setCountLimit(long limit)

u
设定搜索耗时上限

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

u
指定结果所包括的属性集

  • setReturningAttributes(String[] attrs)



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

获取SearchResult封装的条目属性

  • getAttributes()



以上只列举了LDAP操作API的常用部分,更多更详细的描述,请参考 Sun Java6.0 API DOC

LDAP
操作代码样例
在这个章节中,我们将结合LDAP操作的代码实例了解API使用。

初始化LDAP 目录服务上下文
该例子中,我们使用uid=linly,ou=People,dc=jsoso,dc=net这个账号,链接位于本机8389端口的LDAP服务器(ldap://localhost:8389),认证方式采用simple类型,即用户名/密码方式。

Java代码

  1. private static void initialContext() throws NamingException{  

  2.    if(singleton == null){  

  3.        singleton = new LDAPConnection();  

  4.        /*  

  5.         * 在实际编码中,这些环境变量应尽可能通过配置文件读取

  6.         */  

  7.        //LDAP服务地址

  8.        singleton.sLDAP_URL = "ldap://localhost:8389";    

  9.        //管理员账号

  10.        singleton.sMANAGER_DN = "uid=linly,ou=People,dc=jsoso,dc=net";  

  11.        //管理员密码

  12.        singleton.sMANAGER_PASSWORD = "coffee";  

  13.        //认证类型

  14.        singleton.sAUTH_TYPE = "simple";  

  15.        //JNDI Context工厂类

  16.        singleton.sCONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";    


  17.        singleton.envProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, singleton.sCONTEXT_FACTORY);  

  18.        singleton.envProps.setProperty(Context.PROVIDER_URL, singleton.sLDAP_URL);  

  19.        singleton.envProps.setProperty(Context.SECURITY_AUTHENTICATION, singleton.sAUTH_TYPE);  

  20.        singleton.envProps.setProperty(Context.SECURITY_PRINCIPAL, singleton.sMANAGER_DN);  

  21.        singleton.envProps.setProperty(Context.SECURITY_CREDENTIALS, singleton.sMANAGER_PASSWORD);  

  22.        /*  

  23.         * 绑定ldap服务器

  24.         */  

  25.        singleton.dirCtx = new InitialDirContext(singleton.envProps);  

  26.    }  

  27. }  






























通过一个Hashtable或者Properties对象为LDAP的Context设置参数,而后初始化InitialDirContext,即可绑定LDAP服务。这相当于JDBC中获取数据库的Connection对象。

绑定/创建LDAP条目对象
用户可以使用bind方法创建新的LDAP条目,下面的代码创建一个DN:"ou=Employee , dc=jsoso ,dc=net"的OrganizationUnit类LDAP条目如下:

Java代码

  1. public boolean createOrganizationUnit(){  

  2.    String ldapGroupDN = "ou=Employee , dc=jsoso ,dc=net";  

  3.    try {  

  4.        /*  

  5.         * 查找是否已经存在指定的OU条目

  6.         * 如果存在,则打印OU条目的属性信息

  7.         * 如果不存在,则程序会抛出NamingException异常,进入异常处理

  8.         */  

  9.        Attributes attrs = dirContext.getAttributes(ldapGroupDN);  

  10.        System.out.println("Find the group , attributes list :");  

  11.        NamingEnumeration<String>  nEnum = attrs.getIDs();              

  12.        for( ; nEnum.hasMore() ; ){  

  13.            String attrID = nEnum.next();  

  14.            Attribute attr = (Attribute)attrs.get(attrID);  

  15.            System.out.println(attr.toString());  

  16.        }              

  17.        return false;  

  18.    } catch (NamingException e) {  

  19.        /*  

  20.         * 没有找到对应的Group条目,新增Group条目

  21.         */  

  22.        //创建objectclass属性

  23.        Attribute objclass = new BasicAttribute("objectclass");  

  24.        objclass.add("top");  

  25.        objclass.add("organizationalunit");    

  26.        //创建cn属性

  27.        Attribute cn = new BasicAttribute("ou", "Employee");    

  28.        //创建Attributes,并添加objectclass和cn属性

  29.        Attributes attrs = new BasicAttributes();    

  30.        attrs.put(objclass);    

  31.        attrs.put(cn);    

  32.        //将属性绑定到新的条目上,创建该条目

  33.        try {  

  34.            dirContext.bind(ldapGroupDN, null, attrs);  

  35.            System.out.println("Group created successful");  

  36.            return true;  

  37.        } catch (NamingException e1) {  

  38.            e1.printStackTrace();  

  39.        }              

  40.    }  

  41.    return false;  

  42. }  












































或者使用createSubcontext方法创建亦可,以下例子我们新增一个inetorgperson类的LDAP条目:

Java代码

  1. /**  

  2. * 创建LDAP用户条目

  3. * @param user  

  4. * @return  

  5. */  

  6. public boolean createUser(LDAPUser user){  

  7.    if(user == null){  

  8.        return false;  

  9.    }  


  10.    if(user.getUserID() == null || user.getUserID().length() == 0

  11.            || user.getFirstName() == null || user.getFirstName().length() == 0

  12.            || user.getLastName() == null || user.getLastName().length() == 0

  13.            || user.getCommomName() == null || user.getCommomName().length() == 0){  

  14.        return false;  

  15.    }  


  16.    //判断用户条目是否已经存在

  17.    if(isUserexist(user.getDistinguishedName())){  

  18.        return true;  

  19.    }  


  20.    /*  

  21.     * 新建条目属性集

  22.     */  

  23.    Attributes attrs = new BasicAttributes();    

  24.    setBasicAttribute(attrs , "objectclass" , "top,person,organizationalPerson,inetorgperson");  

  25.    setBasicAttribute(attrs , "cn" , user.getCommomName());  

  26.    setBasicAttribute(attrs , "givenname" , user.getFirstName());  

  27.    setBasicAttribute(attrs , "sn" , user.getLastName());  

  28.    setBasicAttribute(attrs , "uid" , user.getUserID());  

  29.    setBasicAttribute(attrs , "userpassword" , user.getPassword());  


  30.    //添加用户条目节点

  31.    try {  

  32.        dirContext.createSubcontext(user.getDistinguishedName(), attrs);  

  33.        System.out.println("Add User(" + user.getDistinguishedName() + ") ok.");    

  34.        return true;  

  35.    } catch (NamingException e) {  

  36.        e.printStackTrace();  

  37.    }    

  38.    return false;  

  39. }  














































获取条目属性
下面一段代码获取entryDN参数指定条目中的属性集合,并打印到控制台

Java代码

  1. /**  

  2. * 获取一个指定的LDAP Entry  

  3. * @param entryDN  

  4. */  

  5. public void find(String entryDN){  

  6.    try {    

  7.        Attributes attrs = dirContext.getAttributes(entryDN);    

  8.        if (attrs != null) {  

  9.            NamingEnumeration<String>  nEnum = attrs.getIDs();  

  10.            for( ; nEnum.hasMore() ; ){  

  11.                String attrID = nEnum.next();  

  12.                Attribute attr = (Attribute)attrs.get(attrID);  

  13.                System.out.println(attr.toString());  

  14.            }  

  15.            System.out.println();  

  16.        }else{    

  17.            System.out.println("No found binding.");  

  18.        }    

  19.    }catch(NamingException ne) {    

  20.        ne.printStackTrace();  

  21.    }    

  22. }  

























修改条目属性
修改DN=user.getDistinguishedName()的条目中的cn、givenname、sn和userpassword四个属性值。
(注:参数DirContext.REPLACE_ATTRIBUTE有另外两个常量:DirContext.ADD_ATTRIBUTE;DirContext.REMOVE_ATTRIBUTE,分别表示新增属性和删除属性。)

Java代码

  1. /**  

  2. * 修改用户信息

  3. * @param user  

  4. * @return  

  5. * @throws Exception  

  6. */    

  7. public boolean modifyUser(LDAPUser user) throws Exception {    

  8.    //用户对象为空

  9.    if (user == null) {    

  10.        throw new Exception("No user information!n");    

  11.    }  


  12.    //检查uid    

  13.    String userDN = user.getDistinguishedName();    

  14.    if (userDN == null && userDN.length() == 0) {    

  15.        throw new NamingException("No userDN you specify!n");    

  16.    }    


  17.    //判断用户条目是否已经存在

  18.    if(!isUserexist(userDN)){  

  19.        return false;  

  20.    }  


  21.    //设置属性

  22.    Attributes attrs = new BasicAttributes();    

  23.    setBasicAttribute(attrs, "cn", user.getCommomName());    

  24.    setBasicAttribute(attrs, "givenname", user.getFirstName());    

  25.    setBasicAttribute(attrs, "sn", user.getLastName());    

  26.    setBasicAttribute(attrs, "userpassword", user.getPassword());      

  27.    //修改属性

  28.    try{  

  29.        dirContext.modifyAttributes(user.getDistinguishedName(),DirContext.REPLACE_ATTRIBUTE, attrs);    

  30.        System.out.println("User(" + user.getDistinguishedName() + ") information modified.n");  

  31.        return true;  

  32.    }catch(NamingException ne){  

  33.        ne.printStackTrace();  

  34.    }  

  35.    return false;  

  36. }  










































删除条目
删除DN= userDN条目

Java代码

  1. /**  

  2. * 删除用户

  3. * @param userDN  

  4. * @return  

  5. */  

  6. public boolean deleteUser(String userDN) {    

  7.    if(!isUserexist(userDN)) {    

  8.        return true;  

  9.    }    

  10.    try {  

  11.        dirContext.destroySubcontext(userDN);  

  12.        System.out.println("User( " + userDN + ") deleted.n");    

  13.        return true;  

  14.    } catch (NamingException e) {  

  15.        e.printStackTrace();  

  16.    }    

  17.    return false;          

  18. }  





















根据属性集搜索条目
根据属性集matchingAttributes中的匹配值,在上下文DN= "ou=People,dc=jsoso ,dc=net"中搜索它的所有子树中的匹配条目。
(注:SearchControls的SCOPE参数详见SearchControls SCOPE补充说明)

Java代码

  1.         /**  

  2. * 通过属性搜索LDAP范例

  3. * @return  

  4. */  

  5. public void searchByAttribute(Attributes matchingAttributes){  

  6.     String baseDN = "ou=People,dc=jsoso ,dc=net";  

  7.     SearchControls cons = new SearchControls();  

  8.     cons.setSearchScope(SearchControls.SUBTREE_SCOPE);  

  9.     try {  

  10.        Name baseName = new LdapName(baseDN);  

  11.        NamingEnumeration<SearchResult> ne = dirContext.search(baseName, matchingAttributes);  

  12.        SearchResult entry = null;  

  13.        for(;ne.hasMore();){  

  14.            entry = ne.next();  

  15. showEntry(entry);  

  16.        }                      

  17.    } catch (NamingException e) {  

  18.        e.printStackTrace();  

  19.    }  

  20. }  























根据过滤器搜索条目
根据过滤器条件,在上下文DN = "ou=People,dc=jsoso ,dc=net"中,搜索它的所有子树中的匹配条目。
(注:过滤器filter的相关语法详见LDAP filter语法补充说明)

Java代码

  1. /**  

  2. * 通过过滤器搜索LDAP范例

  3. * @return  

  4. */  

  5. public void searchByFilter(String filter){  

  6.     String baseDN = "ou=People,dc=jsoso ,dc=net";          

  7.     SearchControls cons = new SearchControls();  

  8.     cons.setSearchScope(SearchControls.SUBTREE_SCOPE);  

  9.     try {  

  10.        NamingEnumeration<SearchResult> ne = dirContext.search(baseDN, filter , cons);  

  11.        SearchResult entry = null;  

  12.        for(;ne.hasMore();){  

  13.            entry = ne.next();  

  14. showEntry(entry);  

  15.        }                      

  16.    } catch (NamingException e) {  

  17.        e.printStackTrace();  

  18.    }  

  19. }  






















相关补充

javax.naming.Name
对象说明
在API中,我们常常见到对LDAP上下文条目有两种参数形式,一种是大家都熟悉的String参数,如: String baseDN = "ou=People,dc=jsoso ,dc=net";
另一种是使用javax.naming.Name类型的参数,那么Name类和String有什么区别呢?
简单的说,Name是对String类DN的封装,它把一个完整的DN字窜分解成了RDN的list。这个list的顺序刚好和String相反。就拿"ou=People,dc=jsoso ,dc=net"为例,Name中的RDN顺序是[0]=net,[1]=jsoso,[2]=People。这样做的好处是更方便对Name进行操作,比如取其前缀或者后缀。

SearchControls SCOPE补充说明


LDAP filter语法补充说明
filter的运算符

filter布尔运算符


搜索过滤器示例

  • 下列过滤器将搜索包含一个或多个 manager 属性值的条目。这也称为存在搜索: manager=*

  • 下列过滤器将搜索包含通用名 Ray Kultgen 的条目。这也称为等价搜索:cn=Ray Kultgen

  • 下列过滤器返回所有不包含通用名 Ray Kultgen 的条目:(!(cn=Ray Kultgen))

  • 下列过滤器返回的所有条目中都有包含子字符串 X.500 的说明属性:description=*X.500*

  • 下列过滤器返回所有组织单元为 Marketing 且说明字段中不包含子字符串 X.500 的条目: (&(ou=Marketing)(!(description=*X.500*)))

  • 下列过滤器返回所有组织单元为 Marketing 且 manager 为 Julie Fulmer 或 Cindy Zwaska 的条目: (&(ou=Marketing)(|(manager=cn=Julie Fulmer,ou=Marketing,dc=siroe,dc=com)(manager=cn=Cindy Zwaska,ou=Marketing,dc=siroe,dc=com)))

  • 下列过滤器返回所有不代表人员的条目: (!(objectClass=person))

  • 下列过滤器返回所有不代表人员且通用名近似于 printer3b 的条目:(&(!(objectClass=person))(cn~=printer3b))



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章