Spring使用LdapTemplate进行LDAP操作

1. LDAP基本概念

轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。
OpenLDAP是轻型目录访问协议(Lightweight Directory Access Protocol,LDAP)。OpenLDAP的使用LMDB数据库软件LMDB是基于Btree-based的高性能mmap key-value数据库,是在BerkeleyDB的基础上改进来的,支持事务操作,支持多进程访问。只产生两个文件data.mdb与lock.mdb

英文简称英文全称含义
DCDomain Component域名的部分,其格式是将完整的域名分成几部分,如域名为xxxx.com变成dc=xxxx,dc=com。简单理解把它理解成域名标识即可
OUOrganization Unit组织单位,组织单位可以包含其他各种对象,如“开发组”(一条记录的所属组织)。简单理解把他理解成公司的组织和单位:ou=开发一组,ou=技术研发单位
UIDUser Id用户ID zhangsan(一条记录的ID)
DNDistinguished Name“uid=zhangsan,ou=开发一组,ou=技术研发单位,dc=xxxx,dc=com”,(注意OU的范围顺序)一条记录的位置(唯一) DN的元素包含UID(或CN) + OU + DC
CNCommon Name公共名称,如“张三”(一条记录的名称)。简单理解用于描述UID的
SNSurname姓,如“张”
rdnRelative dn相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=zhangsan”或“cn= 张三”

2. 示例代码

初始化LdapTemplate

public class LdapUtil {

    /**
     *  初始化LdapTemplate
     * @return
     */
    public static LdapTemplate getLdapTemplate(){
        LdapTemplate template = null;
        try {
            System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
            System.setProperty("java.naming.ldap.attributes.binary", "objectSid");
            LdapContextSource contextSource = new LdapContextSource();

            String url = "ldaps://127.0.0.1:636";
            String base = "DC=domain,DC=com";
            String userDn = "CN=Administrator,CN=Users,DC=domain,DC=com";
            String password = "Letmein123";

            contextSource.setUrl(url);
            contextSource.setBase(base);
            contextSource.setUserDn(userDn);
            contextSource.setPassword(password);
            contextSource.setPooled(false);
            contextSource.afterPropertiesSet(); // important
            Hashtable<String, Object> baseEnvMaps = new Hashtable<String, Object>();
            baseEnvMaps.put("java.naming.ldap.attributes.binary", "objectSid");
            contextSource.setBaseEnvironmentProperties(baseEnvMaps);
            template = new LdapTemplate(contextSource);
            template.setIgnorePartialResultException(true);

        }catch (Exception e){
            e.printStackTrace();
        }
        return template;
    }

    static String getObjectSid(byte[] SID) {
        StringBuilder strSID = new StringBuilder("S-");
        strSID.append(SID[0]).append('-');
        StringBuilder tmpBuff = new StringBuilder();
        for (int t = 2; t <= 7; t++) {
            String hexString = Integer.toHexString(SID[t] & 0xFF);
            tmpBuff.append(hexString);
        }
        strSID.append(Long.parseLong(tmpBuff.toString(), 16));
        int count = SID[1];
        for (int i = 0; i < count; i++) {
            int currSubAuthOffset = i * 4;
            tmpBuff.setLength(0);
            tmpBuff.append(String.format("%02X%02X%02X%02X",
                    (SID[11 + currSubAuthOffset] & 0xFF),
                    (SID[10 + currSubAuthOffset] & 0xFF),
                    (SID[9 + currSubAuthOffset] & 0xFF),
                    (SID[8 + currSubAuthOffset] & 0xFF)));
            strSID.append('-').append(
                    Long.parseLong(tmpBuff.toString(), 16));

        }
        return strSID.toString();
    }
}

LDAP操作

public class Adservice {

    private static final LdapTemplate ldapTemplate = LdapUtil.getLdapTemplate();

    public static void main(String[] args) {
        try {
            //bindOu("sdf");
            //queryGroupByName("jh_group_test");
            //createGroup("jh_group_test");
            //removeMemberToGroup("jh_group_test","jhuser3");
            //addprimaryGroupID("jhtest");
            //queryGroupByName("jh_group_test");
            //bindUser("jhuser");
            addMemberToGroup("jh_group_test", "jhuser");
            //getSid("dusers");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void bindUser(String name) {
        try {
            Attributes attributes = new BasicAttributes();

            attributes.put("objectclass", "user");
            attributes.put("name", name);
            attributes.put("displayname", name);
            attributes.put( "sAMAccountName", name);
            attributes.put("description", "测试用户1111111111111");
            attributes.put("gidNumber", "22345678");
            attributes.put("uidNumber", "16677777");
            ldapTemplate.bind("CN=" + name + ",CN=Users", null, attributes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createGroup(String name) throws Exception {
        try {
            Attributes attributes = new BasicAttributes();

            attributes.put("objectclass", "group");
            attributes.put("name", name);
            attributes.put("displayname", name);
            attributes.put("description", "测试组11111111111");

            ldapTemplate.bind("CN=" + name + ",CN=Users", null, attributes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void queryGroupByName(String name) {
        LdapQuery query = LdapQueryBuilder.query().where("objectclass").is("group")
                .and("name").is(name);
        List<Map<String, Object>> search = ldapTemplate.search(query, (AttributesMapper<Map<String, Object>>) (attributes) -> {
            Map<String, Object> map = new HashMap<>();
            try {
                Attribute number = attributes.get("gidNumber");
                if (number != null) {
                    String gidNumber = number.get().toString();
                    map.put("gidNumber", gidNumber);
                }
                String distinguishedName = attributes.get("distinguishedName").get().toString();
                NamingEnumeration<?> member = attributes.get("member").getAll();
                List<String> list = new ArrayList<>();
                while (member.hasMore()) {
                    String next = member.next().toString();
                    list.add(next);
                }

                map.put("distinguishedName", distinguishedName);
                map.put("member", list);
            } catch (NamingException e) {
                e.printStackTrace();
            }
            return map;
        });
        System.out.println(search);
    }

    private static void delete(String name) {

        ldapTemplate.unbind("CN=" + name + ",CN=Users");
    }

    public static void addMemberToGroup(String groupName, String username) {
        String groupDn = "CN=" + groupName + ",CN=Users";
        String userDn = "CN=" + username + ",CN=Users";
        String jhuser1 = "CN=jhuser1,CN=Users";

        DirContextOperations ctxUser = ldapTemplate.lookupContext(userDn);
        //DirContextOperations ctxUser1 = ldapTemplate.lookupContext(jhuser1);
        //DirContextOperations ctxGroup = ldapTemplate.lookupContext(groupDn);
        try {
            String distinguishedname = ctxUser.getStringAttribute("distinguishedname");
            //String distinguishedname1 = ctxUser1.getStringAttribute("distinguishedname");
            //ctxGroup.addAttributeValue("member", distinguishedname);
            //ctxGroup.addAttributeValue("member", distinguishedname1);
            //ldapTemplate.modifyAttributes(ctxGroup);

            List<ModificationItem> itemList = new ArrayList<>();
            ModificationItem primaryGroupIDItem = new ModificationItem(DirContext.ADD_ATTRIBUTE,
                    new BasicAttribute("member", distinguishedname));
            itemList.add(primaryGroupIDItem);
            ModificationItem[] modificationItems = itemList.toArray(new ModificationItem[itemList.size()]);
            ldapTemplate.modifyAttributes(groupDn, modificationItems);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void addprimaryGroupID(String username) {
        String userDn = "CN=" + username + ",CN=Users";

        List<ModificationItem> itemList = new ArrayList<>();
        ModificationItem gidNumberItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                new BasicAttribute("primaryGroupID", "1720"));
        itemList.add(gidNumberItem);
        ModificationItem[] modificationItems = itemList.toArray(new ModificationItem[itemList.size()]);
        ldapTemplate.modifyAttributes(userDn, modificationItems);
    }

    public static void removeMemberToGroup(String groupName, String username) {
        String groupDn = "CN=" + groupName + ",CN=Users";
        String userDn = "CN=" + username + ",CN=Users";
        DirContextOperations ctxGroup = ldapTemplate.lookupContext(groupDn);
        DirContextOperations ctxUser = ldapTemplate.lookupContext(userDn);
        ctxGroup.removeAttributeValue("member", ctxUser.getStringAttribute("distinguishedname"));
        ldapTemplate.modifyAttributes(ctxGroup);
    }

    public static void bindOu(String name) {
        String ou = "OU=sdf,OU=DD,OU=xian,OU=China";
        try {
            Attributes attributes = new BasicAttributes();

            attributes.put("objectclass", "organizationalUnit");
            attributes.put("name", name);
            attributes.put("displayname", name);
            attributes.put("description", "测试组织单位11111111111");

            ldapTemplate.bind(ou, null, attributes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void getSid(String groupName) {
        String groupDn = "CN=" + groupName + ",CN=Users";

        List<String> list = ldapTemplate.search(
                LdapQueryBuilder.query().where("objectclass").is("group")
                        .and("name").is(groupName),
                (AttributesMapper<String>) (attributes) -> {
                    String objectSidStr = null;
                    try {
                        Object objectSid = attributes.get("objectSid").get();
                        objectSidStr = LdapUtil.getObjectSid((byte[]) objectSid);

                    } catch (NamingException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return objectSidStr;
                });

        System.out.print(list.toString());
    }
}

3. 常见问题

3.1 ObjectSid,objectGUID乱码

Map<String, Object> config = new HashMap<>();
config.put(“java.naming.ldap.attributes.binary”, “objectGUID”);
contextSource.setBaseEnvironmentProperties(config);

3.2 Java采用SSL连接AD域连接出错问题simple bind failed:IP:PORT解决方案

https://blog.csdn.net/hct368/article/details/97247258

3.3 添加,修改数组类型的AD属性

https://stackoverflow.com/questions/33363080/spring-malformed-member-attribute-value

3.4 javax.naming.CommunicationException:simple bind faild

https://blog.csdn.net/leinminna/article/details/114009448

3.5 Spring’s LdapTemplate search: PartialResultException: Unprocessed Continuation Reference(s); remaining name ‘/’

https://stackoverflow.com/questions/37486159/springs-ldaptemplate-search-partialresultexception-unprocessed-continuation-r


版权声明:本文为XSemperFI原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。