java调用域控服务实现部门用户增删改查

原创内容,爬取请指明出处:https://www.cnblogs.com/Lucy151213/p/11005298.html

公司做大后,用到的系统就会越来越多,来个新员工,需要在HR系统添加,然后再到域控系统添加,可能还需要到NC,OA等系统添加账号。后来公司引入总线系统,来个新员工只需要在HR系统添加账号,HR系统把员工信息下发到总线系统,总线系统再下发到其他各个系统,这样能保证数据的一致性。

我负责的那块就是让域控系统接收总线系统下发的员工信息。我在域控服务与总线系统中间搭建一层restful的服务,用于接收解析总线请求,调用相应域控方法。

在开发过程中花最多时间的地方是在证书认证那块,针对修改密码这种包含敏感信息的方法,需用LDAP协议才能实现。

  • 域控服务安装

什么是域控服务,参考下面的链接可以对域控有个大概了解:

https://www.cnblogs.com/cnjavahome/p/9029665.html

怎么安装AD证书,我是参考如下文章安装的:

https://blog.csdn.net/hc1017/article/details/81293323

  • 证书导出

导出证书步骤也可以参考上面的链接:https://blog.csdn.net/hc1017/article/details/81293323 。需要注意一点是链接里面证书导出选择的是’DER编码二进制X.509(.CER)(D)’,我们这里需要选择’Base64编码X.509(.CER)(S)’,我之前选择DER那种格式就是不成功,换成Base64才成功的(几种格式试出来的o(╥﹏╥)o)。

给导出的证书取名为cert.cer,文件长这样:

执行下面的命令(需把keytool所在目录设置为系统变量,位置在:C:\Program Files\Java\jre1.8.0_102\bin):

keytool -importcert -keystore F:/yourpath/security.keystore -storepass 123456 -keypass 123456 -alias security -file F:/cert.cer

生成一个叫做security.keystore的文件,将这个文件拷贝到你的Java目录下面,如:C:\Program Files\Java\jre1.8.0_102\lib\security

  • 中间服务开发

部门或者员工都有编号这个属性,但是域控服务没有这个属性,我把部门编号,员工编号放在域控的属性‘描述’里面,对应的字段叫做‘description’。

全局文件配置如下:

①添加更新部门

Properties env = new Properties();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"
        env.put(Context.SECURITY_PRINCIPAL, ADMINNAME);// AD User
        env.put(Context.SECURITY_CREDENTIALS, ADMINPASSWORD);// AD Password
        env.put(Context.PROVIDER_URL, LDAPURL);// LDAP工厂类

        LdapContext ctx = null;
        try {
            ctx = new InitialLdapContext(env, null);
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(&(objectClass=organizationalUnit)(description=" + departId + "))";//查询这个部门信息
            String searchBase = "OU=实际情况,DC=实际情况,DC=com";//在整个公司查找指定description
            String returnedAtts[] = {"name", "description", "distinguishedName"};//用于获取组织机构

            searchCtls.setReturningAttributes(returnedAtts);
            boolean isDepartExits = false;
            NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
            while (answer.hasMoreElements()) {//理论上id是不会重复的,所以这边parentDC只会赋值一次
                isDepartExits = true;//如果找到值,那么就表示有这个部门,就更新
                SearchResult sr = answer.next();
                Attributes Attrs = sr.getAttributes();//得到符合条件的属性集
                if (Attrs != null) {
                    for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore(); ) {
                        Attribute Attr = (Attribute) ne.next();//得到下一个属性
                        if ("distinguishedName".equals(Attr.getID())) {
                            for (NamingEnumeration e = Attr.getAll(); e.hasMore(); ) {
                                String userInfo = e.next().toString();
                                departDC = userInfo;
                                System.out.print(userInfo);
                            }
                        }
                        System.out.println("");
                    }
                }
            }

            if (isDepartExits) {//这个部门id存在,那么如果传入的部门名称不相同,就更新部门名称,相同就不做处理
                if (!isNullOrEmpty(departDC)) {
                    String[] dcs = departDC.split(",");
                    if (dcs.length > 0) {//名称不相同表示修改了部门名称,那么就修改
                        if (!((dcs[0].substring(dcs[0].indexOf("=") + 1)).equals(departName))) {
                            String newDc = "OU=" + departName + departDC.substring(departDC.indexOf(","), departDC.length());
                            ctx.rename(departDC, newDc);
                            retMsg.setSuccess(true);
                            retMsg.setMsg("更新成功");
                            retMsg.setUid(departId);
                            logger.info("更新部门成功。   departId:"+departId+"  departDC:"+departDC);
                        } else {
                            retMsg.setSuccess(true);
                            retMsg.setMsg("部门名字未做修改,不处理");
                            retMsg.setUid(departId);
                            logger.info("部门名称未做修改,不予更新。  departId:"+departId+"  departDC:"+departDC);
                        }

                    }
                }
            } else {//添加新部门,首先检查父id是否有效
                String searchFilter1 = "(&(objectClass=organizationalUnit)(description=" + parentId + "))";//查询父id信息
                NamingEnumeration<SearchResult> answer1 = ctx.search(searchBase, searchFilter1, searchCtls);
                while (answer1.hasMoreElements()) {//理论上id是不会重复的,所以这边parentDC只会赋值一次
                    SearchResult sr = answer1.next();
                    Attributes Attrs = sr.getAttributes();//得到符合条件的属性集
                    if (Attrs != null) {
                        for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore(); ) {
                            Attribute Attr = (Attribute) ne.next();//得到下一个属性
                            if ("distinguishedName".equals(Attr.getID())) {
                                for (NamingEnumeration e = Attr.getAll(); e.hasMore(); ) {
                                    String userInfo = e.next().toString();
                                    parentDC = userInfo;
                                }
                            }
                        }
                    }
                }

                if (isNullOrEmpty(parentDC)) {
                    logger.error("父组织的id不存在。 departId:"+departId);
                    return getNoParamDataMessage("父组织的id不存在");
                } else {
                    ldapGroupDN = "OU=" + departName + "," + parentDC;
                    //查询这个departId是否存在
                    try {
                        Attributes attrs = ctx.getAttributes(parentDC);//note......
                        NamingEnumeration<String> nEnum = attrs.getIDs();
                        //如果没有报错,说明有这个组织的dn,那么如果明知不相同
                        Attributes attrs1 = new BasicAttributes();
                        attrs1.put("objectClass", "organizationalunit");
                        attrs1.put("description", departId);//部门的id放在description下面
                        ctx.createSubcontext(ldapGroupDN, attrs1);
                        retMsg.setSuccess(true);
                        retMsg.setMsg("添加成功");
                        retMsg.setUid(departId);
                        logger.info("部门添加成功。 departId:"+departId+"  departDC:"+ldapGroupDN);
                    } catch (Exception ex) {
                        logger.error("添加部门发生异常。departId:"+departId+"  departDC:"+ldapGroupDN+"  。ex:"+ex.getMessage());
                        logger.error("stack:"+ex.getStackTrace());
                    }

                }
            }

            ctx.close();
        } catch (NamingException e) {
            logger.error("添加或者更新部门发生异常。departId:"+departId+"  stack:"+e.getStackTrace());
            retMsg.setUid(departId);
            retMsg.setSuccess(false);
            retMsg.setMsg("失败");
            ctx.close();
        }

②删除部门

和上面的代码类似,在获取到departDC后执行:ctx.destroySubcontext(departDC);

③添加更新用户

之前写的挫,每次添加更新我就创建一次连接,有一次传很多用户过来,然后速度就很慢,所有把创建连接提出来。

循环调用添加/更新用户方法:

LdapContext ctx = null;
        LdapContext sslCtx = null;
        try {
            Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"
            env.put(Context.SECURITY_PRINCIPAL, ADMINNAME);// AD User
            env.put(Context.SECURITY_CREDENTIALS, ADMINPASSWORD);// AD Password
            env.put(Context.PROVIDER_URL, LDAPURL);// LDAP工厂类
            ctx = new InitialLdapContext(env, null);
            sslCtx = getSslConn();
            for (UserEntity u :
                    users) {
                dataMessageList.add(ADHelpUtil.addUserNew(u,ctx,sslCtx));
            }
            ctx.close();
            sslCtx.close();
        }catch (Exception ex){
            logger.error("新方法添加用户异常。ex:"+ex.getMessage());
            try {
                ctx.close();
                sslCtx.close();
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }

获取SSL连接代码如下:

Properties env = new Properties();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"
        env.put(Context.SECURITY_PRINCIPAL, ADMINNAME);// AD User
        env.put(Context.SECURITY_CREDENTIALS, ADMINPASSWORD);// AD Password
        env.put(Context.SECURITY_PROTOCOL, "ssl");
        env.put(Context.PROVIDER_URL, LDAPSURL);// LDAP工厂类
        System.setProperty("javax.net.ssl.trustStore", TRUST_STORE_PATH);
        System.setProperty("javax.net.ssl.trustStorePassword", TRUST_STORE_PASSWORD);
        LdapContext ctx = null;
        try {
            ctx = new InitialLdapContext(env, null);
            return ctx;
        }catch (Exception ex){
            System.out.println("Problem resetting password: " + ex);
            ex.printStackTrace();
        }

添加方法代码片段如下:

try {
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(&(objectClass=user)(description=" + uid + "))";//查询这个用户信息
            String searchBase = "OU=实际情况,DC=实际情况,DC=com";//在整个公司查找指定description
            String returnedAtts[] = {"name", "description", "distinguishedName"};//用于获取组织机构

            searchCtls.setReturningAttributes(returnedAtts);
            boolean isUserExits = false;
            NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
            if(answer.hasMoreElements()){//理论上id是不会重复的,所以这边usertDC只会赋值一次
                isUserExits = true;//如果找到值,那么就表示有这个部门,就更新
                userDC = getDistinguishedName(answer);
            }

            //检测部门编号查询部门是否存在,不存在抛挫,代码省略
            //检测传入的员工经理是否有效,无需抛挫,代码省略

            if (isUserExits) {//用户存在,如果名或姓或部门id有变化,就修改
                if (!isNullOrEmpty(userDC)) {
                    //如果用户cancel=1,就直接停用,不用去修改其他属性
                    if("1".equals(canceld)){//启用停用需要使用ssl协议
                        ModificationItem[] mods = new ModificationItem[1];
                        mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                                new BasicAttribute("userAccountControl",
                                        Integer.toString(DONT_EXPIRE_PASSWORD+UF_NORMAL_ACCOUNT+ACCOUNTDISABLE)));
                        if(null!=sslCtx){
                            sslCtx.modifyAttributes(userDC, mods);
                            logger.error("禁用客户成功 userid:"+uid+"  userDC:"+userDC);
                        }else {
                            logger.error("禁用客户失败,SSL失败 userid:"+uid+"  userDC:"+userDC);
                            return getNoParamDataMessage("禁用客户失败,SSL失败");
                        }
                        mods = null;
                    }else {
                        String curDepDC = userDC.substring(userDC.indexOf(",") + 1, userDC.length());
                        String newDc = userDC;
                        if (!curDepDC.equals(departDC)) {//说明用户是要修改所在部门
                            newDc = userDC.substring(0, userDC.indexOf(",")) + "," + departDC;
                            ctx.rename(userDC, newDc);//换部门
                        }
                        //修改员工属性
                        //设置属性
                        Attributes attrs = new BasicAttributes();
                        attrs.put("displayName", lastName + firstName);
                        attrs.put("description", uid);
                        attrs.put("mail", email);
                        attrs.put("userPrincipalName", email);

                        if(null!=company&&!"".equals(company))
                            attrs.put("company", company);
                        if(null!=title&&!"".equals(title))
                            attrs.put("title", title);
                        if(null!=officePhone&&!"".equals(officePhone))
                            attrs.put("telephoneNumber", officePhone);
                        if(null!=mobile&&!"".equals(mobile))
                            attrs.put("mobile", mobile);
                        if(!isNullOrEmpty(managerDC))
                            attrs.put("manager",managerDC);
                        if(departDC.length()!=0) {
                            int ind1 = departDC.indexOf("=");
                            int ind2 = departDC.indexOf(",");
                            if(ind1!=-1 && ind2!=-1)
                                attrs.put(new BasicAttribute("department", departDC.substring(ind1+1,ind2)));
                        }
                        ctx.modifyAttributes(newDc, DirContext.REPLACE_ATTRIBUTE, attrs);
                    }
                }
            } else {//添加新用户
                Attribute objclass = new BasicAttribute("objectclass");
                objclass.add("top");
                objclass.add("user");
                Attributes attrs1 = new BasicAttributes();
                attrs1.put(objclass);
                attrs1.put(new BasicAttribute("givenname", firstName));
                attrs1.put(new BasicAttribute("sn", lastName));
                attrs1.put(new BasicAttribute("displayName", lastName + firstName));
                attrs1.put(new BasicAttribute("description", uid));
                attrs1.put(new BasicAttribute("mail", email));
                if(departDC.length()!=0) {
                    int ind1 = departDC.indexOf("=");
                    int ind2 = departDC.indexOf(",");
                    if(ind1!=-1 && ind2!=-1)
                        attrs1.put(new BasicAttribute("department", departDC.substring(ind1+1,ind2)));
                }
                attrs1.put(new BasicAttribute("sAMAccountName", email.substring(0, email.indexOf("@"))));
                attrs1.put(new BasicAttribute("userPrincipalName", email));
                if(null!=company && !"".equals(company))
                    attrs1.put(new BasicAttribute("company", company));
                if(null!=title && !"".equals(title))
                    attrs1.put(new BasicAttribute("title", title));
                if(null!=officePhone && !"".equals(officePhone))
                    attrs1.put(new BasicAttribute("telephoneNumber", officePhone));
                if(null!=mobile && !"".equals(mobile))
                    attrs1.put(new BasicAttribute("mobile", mobile));
                if(!isNullOrEmpty(managerDC))
                    attrs1.put(new BasicAttribute("manager",managerDC));

                String newDc = "CN=" + lastName + firstName + "," + departDC;//新用户的dn
                ctx.createSubcontext(newDc,attrs1);

                ModificationItem[] mods = new ModificationItem[2];
                String newQuotedPassword = "\"" + COMMON_PASSWORD + "\"";
                byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
                mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                        new BasicAttribute("unicodePwd", newUnicodePassword));
                mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                        new BasicAttribute("userAccountControl",
                                Integer.toString(UF_NORMAL_ACCOUNT
                                        + UF_PASSWORD_EXPIRED + UF_PASSWD_NOTREQD)));
                if(null!=sslCtx){
                    sslCtx.modifyAttributes(newDc, mods);
                }

                mods = null;
            }
        }catch (NameAlreadyBoundException ex){
            logger.error("异常:uid:"+uid+" userDC:"+userDC+" ex:"+ex.getMessage());
        }
        catch (Exception e) {
            logger.error("异常:uid:"+uid+" userDC:"+userDC+" ex:"+e.getMessage());
        }

④删除用户

核心代码,查询到userDC后,执行:ctx.destroySubcontext(userDC);

⑤获取员工列表(传入上级部门编号)

与上面的代码雷同,省略

⑥获取部门列表(传入上级部门编号)

与上面的代码雷同,省略

原文地址:https://www.cnblogs.com/Lucy151213/p/11005298.html

时间: 2024-11-05 20:43:28

java调用域控服务实现部门用户增删改查的相关文章

Windows server 2008 R2 配置AD域控服务并为用户设置统一桌面

作为AD域服务器,使用静态IP地址,并且DNS地址与IP地址相同 如果先新建的DHCP服务器,在建完AD后对DHCP服务器添加授权,保证服务器与客户端能ping通 打开服务器管理器,添加角色,添加Active Directory域服务,直接安装 打开命令行,输入:"dcpromo" 进行AD域服务的安装 搭建第一台域控服务器,选择在新林中新建域 填写域名 设置级别 如果没有安装DNS服务器的话,在这一步安装,我已经安装好了,直接下一步 选择"是" 保持默认,下一步

Mybatis实现部门表增删改查以及排序

废话不说,直接开门见山! 需要在WebContent下的lib下导入两个包 mybatis-3.2.5.jar ojdbc6.jar 1 package com.xdl.entity; 2 3 import java.io.Serializable; 4 5 public class Dept implements Serializable{ 6 private Integer deptno;//类型和名称与表保持一致 7 private String dname; 8 private Stri

Spring mvc整合mybatis基于mysql数据库实现用户增删改查及其分页显示的完整入门实例【转】

Spring mvc整合mybatis例子, 基于mysql数据库实现对用户的增.删.改.查,及分页显示的完整例子. 查询显示用户 添加用户 更新用户 官方验证: 项目截图 必须修改applicationContext.xml中mysql的配置为本地的,否则启动失败. 另外jar包多一个ehcache.jar无关紧要,删除即可. 1. 使用阿里巴巴Druid连接池(高效.功能强大.可扩展性好的数据库连接池.监控数据库访问性能.支持Common-Logging.Log4j和JdkLog,监控数据库

JSP+Servlet+Ajax实现用户增删改查的例子

一.数据库设计 [用户表User] 已有的测试数据 二.Java代码编写 Java EE的架构一般分为以下五层: ①.Domain ②.DAO ③.Service ④.Controller ⑤.View 这里的项目结构如下: 1.Domain层 User.java 1 package domain; 2 3 import java.util.Date; 4 5 public class User { 6 7 public User() { 8 9 } 10 11 private Integer

maven+springMVC+mybatis+easyUI管理用户增删改查

1.项目演示图 2.项目简介 项目分为两个工程domain和manager,工程结构如下图所示,其中domain是Maven java工程主要完成对数据库的操作,manager是Maven Web工程,完成web访问,manager依赖于domain 3.项目源码下载地址

java图书管理的一个小模块(增删改查,不使用数据库)

图书管理模块:某图书管需要对图书进行信息化管理,要求管理员能够进行新增图书,能按照书名进行模糊查看图书能进行价格统计 系统实现如下:1.新增2.查询3.统计价格 1请输入新书:图书号,书名,作者,价格 新增成功,选择其他操作1.新增2.查询3.统计价格 2请输入书名:水1002,水浒传,施耐庵,1081003,喝水好处多,张三,199 选择其他操作1.新增2.查询3.统计价格 3总计:图书10本,价格1020元 //////////////////////////////////////////

ASP.NET学习笔记(2)——用户增删改查

说明(2017-7-4 11:48:50): 1. index.html 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <

JAVA 操作远程mysql数据库实现单表增删改查操作

package MysqlTest; import java.sql.DriverManager; import java.sql.ResultSet; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; import com.mysql.jdbc.Statement; public class MysqlTest02 { public static void main(String[] args)

Linux 学习 - 用户增删改查 相关操作

useradd  增加/创建用户 userdel -r  删除用户 id shizhengwen  查看用户 (shizhengwen是用户名) usermod -d 修改的是 用户的配置文件 中的 家目录 ,修改之后 还需要复制 原来 家目录中的配置文件,否则 无法正常登录用户(相当于他重新创建了一个新的家目录文件,文件内是空的) usermod -G group1 user1 将用户user1,加入到group1 这个组内, 注意,这里新加入的组 是 副组 ,是覆盖的形式, 意思是说,如果再