java ldap组织架构信息定时同步AD域

AD域简单介绍

AD域的存储结构跟我们所用的文件夹一样,所以要定位某个文件就需要它的文件路径。然后对它做增删改查。
组织:
OU=100.27.04,OU=100.27,OU=100,OU=wall,DC=gwtest,DC=com,DC=cn
人员:
CN=100000,OU=100.27.04,OU=100.27,OU=100,OU=wall,DC=test,DC=com,DC=cn
正常系统是区分组织和部门的,域中就不需要这个概念了,部门就变成一层一层的了,这个OU就相当于一层一层的文件路径,CN就是特定的文件,设置不同类型就是不同文件 就像 word excel等。
OU=wall,DC=gwtest,DC=com,DC=cn 就相当于指定服务器的信息路径。

需求解析

组织/部门

新增/部门

组织/部门新增就相当于在域中创建对应的OU,流程如下
在这里插入图片描述

修改

这里涉及一个点就是,很多组织都有相同的部门,比如财务部,人力资源部等等。单独拿出某个部门就不清楚是那个组织下的,定义了新的需求所有部门岗位的名称都要 “组织_多级部门_多级岗位”这样展示。
在这里插入图片描述

停用

需求上没有要组织停用的功能,只要求了部门停用。停用对应域内删除,很简单就不画流程图了,就是找到对应部门OU 删除即可。

组织/部门调动

这个调动因为产品设计时间轴的概念不是和好实现,所以定时就抓取不到调动前的数据,所以商量设计成为实时同步。流程也很简单。
在这里插入图片描述

岗位

岗位在域那边对应通讯组方便后续OA对接,岗位的地址也跟人员一样有CN只不过类型不一样,CN=100000,OU=100.27.04,OU=100.27,OU=100,OU=wall,DC=test,DC=com,DC=cn,刚为放在部门下与人员同级。

新增

新增流程同组织新增

修改

修改流程同组织修改

调动

岗位调动影响人员信息在人员信息中处理

人员

新增

人员新增流程如下
在这里插入图片描述

调动

人员调动流程如下
在这里插入图片描述

修改

停用

开发解析

连接域的工具类

连接域

非证书方式
连接代码
			Properties mEnv = new Properties();
			mEnv.put(Context.AUTHORITATIVE, "true");
			mEnv.put(Context.SECURITY_PROTOCOL, "ssl");
			mEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
			mEnv.put(Context.PROVIDER_URL,Url);
			mEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
			mEnv.put(Context.SECURITY_PRINCIPAL, user);
			mEnv.put(Context.SECURITY_CREDENTIALS, password);
			//关键代码,注意对应的DummySSLSocketFactory这个类的包路径要正确,
			
	       	mEnv.put("java.naming.ldap.factory.socket", "nc.ctjt.itf.arap.DummySSLSocketFactory");
	       	dc = new InitialLdapContext(mEnv, null);
证书方式

首先要导入证书,要导入到jdk中命令如下

keytool -import -keystore /media/data/java-1.8.0-openjdk/jre/lib/security/cacerts -storepass changeit -keypass changeit -alias ca4 -file /media/data/demo/ca4.cer -trustcacerts

导入位置 /media/data/java-1.8.0-openjdk/jre/lib/security/cacerts
别名 ca4
文件所在位置 /media/data/demo/ca4.cer

连接代码
			Properties env = new Properties();
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
			env.put(Context.SECURITY_AUTHENTICATION, "simple");
			env.put(Context.SECURITY_PRINCIPAL, user);
			env.put(Context.SECURITY_CREDENTIALS, password);
			env.put(Context.PROVIDER_URL,Url);
			env.put(Context.AUTHORITATIVE, "true");
			System.setProperty("javax.net.ssl.trustStore",keystore);
			env.put(Context.SECURITY_PROTOCOL, "ssl");
			dc = new InitialLdapContext(env,null);

关闭域

	public void close() throws BusinessException {
		if (dc != null) {
			try {
				dc.close();
			} catch (NamingException e) {
				throw new BusinessException("AD域关闭异常,"+e.getMessage());
			}
		}
	}

查询用户属性

searchBase 用户的OU
userName 用户属性 一般都是编码

	public boolean searchByUserName(String searchBase, String userName) throws BusinessException {
		
		SearchControls searchCtls = new SearchControls();
		searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
		String searchFilter = "cn=" + userName;
		String returnedAtts[] = { "cn" }; // 定制返回属性
		searchCtls.setReturningAttributes(returnedAtts); // 设置返回属性集
		try {
			NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
			if(answer.hasMoreElements()) {
				SearchResult sr = (SearchResult) answer.next();
				Attribute displayName = sr.getAttributes().get("cn");
				if(userName.equals(displayName.get())) {
					return false;
				}
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

查询岗位组

	@Override
	public boolean searchByUserGroup(String searchBase, String userName) throws BusinessException {
		SearchControls searchCtls = new SearchControls();
		searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
		String searchFilter = "member" + userName;
		String returnedAtts[] = {"member"}; // 定制返回属性
		searchCtls.setReturningAttributes(returnedAtts); // 设置返回属性集
		try {
			NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
			if(answer.hasMoreElements()) {
				SearchResult sr = (SearchResult) answer.next();
				Attribute displayName = sr.getAttributes().get("member");
				if(userName.equals(displayName.get())) {
					return false;
				}
			}
		} catch (Exception e) {
			return true;
		}
		return true;
	}

查询组织信息

		@Override
	public boolean searchByOrg(String searchBase,String name ,String description,String displayName) throws BusinessException {
		SearchControls searchCtls = new SearchControls();
		searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        String searchFilter = "name=" + name;
        String returnedAtts[] = { "description","displayName","name"}; //定制返回属性
		searchCtls.setReturningAttributes(returnedAtts); // 设置返回属性集
		try {
			NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
			if(answer.hasMoreElements()) {
				SearchResult sr = (SearchResult) answer.next();
				Attribute AD_description = sr.getAttributes().get("description");
				Attribute AD_displayName = sr.getAttributes().get("displayname");
				if(StringUtil.isNotBlank(description)&&StringUtil.isNotBlank(displayName))
				//两边空
				if(displayName == null && AD_displayName.get() == null) {
					if(description.equals(AD_description.get())) {
						return true;
					}
				}else {
					if(displayName.equals(AD_displayName.get()) && description.equals(AD_description.get())) {
						return true;
					}
				}
			}
		} catch (Exception e) {
			return false;
		}
		return false;
	}

修改密码

	@Override
	public void updatePwd(String base, String pwd) {
		try {
			ModificationItem[] mods = new ModificationItem[1];
			String password = "\"" + pwd + "\"";
			byte[] newUnicodePassword = password.getBytes(StandardCharsets.UTF_16LE);
			mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
					new BasicAttribute("unicodePwd", newUnicodePassword));

			dc.modifyAttributes(base, mods);
			System.out.println("修改密码成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

新增人员

@Override
	public boolean add(HRADVo psndoc, String base) throws BusinessException {
		
		try {
			Attributes attrs = new BasicAttributes(true);
			if(StringUtil.isNotBlank(psndoc.getEmail())) {
				attrs.put("mail", psndoc.getEmail());
				attrs.put("UserPrincipalName", psndoc.getEmail());
			}
			if(StringUtil.isNotBlank(psndoc.getCode())) {
				attrs.put("EmployeeNumber", psndoc.getCode());
				attrs.put("cn", psndoc.getCode());// 新增用户名称
				attrs.put("SamAccountName", psndoc.getCode());
			}
			if(StringUtil.isNotBlank(psndoc.getMobile())) {
				attrs.put("mobile", psndoc.getMobile());
			}
			if(StringUtil.isNotBlank(psndoc.getName())) {
				attrs.put("displayName", psndoc.getName());//
			}

			if(StringUtil.isNotBlank(psndoc.getOfficephone())) {
				attrs.put("telephoneNumber", psndoc.getOfficephone());//
			}
	
			attrs.put("objectclass", "user");
			attrs.put("userAccountControl", "****");
			// 设置为0.用户首次登录需要改密码
			attrs.put("pwdLastSet", "0");
			// 设置默认密码
			String password = "\"" + "******" + "\"";
			byte[] newUnicodePassword = password.getBytes(StandardCharsets.UTF_16LE);
			attrs.put("unicodePwd", newUnicodePassword);// 默认密码
			dc.createSubcontext(base, attrs);
			Logger.error("新增AD域用户成功:" + psndoc.getCode());
		} catch (Exception e) {
			return false;
		}
		return true;
	}

调动用户

	public boolean turnUser(String oldName, String newName) throws BusinessException { 
        try {
        	dc.rename(oldName, newName);
		} catch (NamingException e) {
			return false;
		}
		return true;
	}

修改用户属性

	public boolean modifyUser(HRADVo psndoc, String base) throws BusinessException { 
		//设置属性 
        //修改的属性
        List<ModificationItem> mList = new ArrayList<ModificationItem>();
		if(StringUtil.isNotBlank(psndoc.getEmail())) {
			mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail", psndoc.getEmail())));
			 mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("UserPrincipalName", psndoc.getEmail())));
		}
		if(StringUtil.isNotBlank(psndoc.getCode())) {
	        mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("EmployeeNumber", psndoc.getCode())));
	        mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("SamAccountName", psndoc.getCode())));
		}
		if(StringUtil.isNotBlank(psndoc.getMobile())) {
			 mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mobile", psndoc.getMobile())));
		}

		if(StringUtil.isNotBlank(psndoc.getName())) {
			mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName", psndoc.getName())));
		}

		if(StringUtil.isNotBlank(psndoc.getOfficephone())) {
			mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("telephoneNumber", psndoc.getOfficephone())));
		}
    	//集合转为数组
        ModificationItem[] mArray = new ModificationItem[mList.size()];
        for (int i = 0; i < mList.size(); i++) {
            mArray[i] = mList.get(i);
        }
        try {
			dc.modifyAttributes(base, mArray);
		} catch (NamingException e) {
			return false;
		}
		return true;
	}

修改组织信息

		public boolean modifyOrg(HRADVo HRADVo, String base) throws BusinessException { 
		//设置属性 

        
        //修改的属性
        List<ModificationItem> mList = new ArrayList<ModificationItem>();
        //不能修改
        //mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userAccountControl", person.getUserAccountControl())));
//        mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("EmailAddress", psndoc.getEmail())));

		if(StringUtil.isNotBlank(HRADVo.getShortname())) {
	        mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName", HRADVo.getName())));
		}
      
    	//集合转为数组
        ModificationItem[] mArray = new ModificationItem[mList.size()];
        for (int i = 0; i < mList.size(); i++) {
            mArray[i] = mList.get(i);
        }
        try {
			dc.modifyAttributes(base, mArray);
		} catch (NamingException e) {
			return false;
		}
		return true;
		
	}

修改岗位信息

	public boolean modifyPost(String description, String base) throws BusinessException { 
		//设置属性 

        
        //修改的属性
        List<ModificationItem> mList = new ArrayList<ModificationItem>();
        //不能修改
		if(StringUtil.isNotBlank(description)) {
			mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("description", description)));
		}
      
    	//集合转为数组
        ModificationItem[] mArray = new ModificationItem[mList.size()];
        for (int i = 0; i < mList.size(); i++) {
            mArray[i] = mList.get(i);
        }
        try {
			dc.modifyAttributes(base, mArray);
		} catch (NamingException e) {
			return false;
		}
		return true;
		
	}

查询并创建组织

	 public boolean getOU(String ldapGroupDN,HashMap map) throws BusinessException{
		try {
			dc.getAttributes(ldapGroupDN);
			return true;
		} catch (NamingException e) {
			/*
			 * 没有找到对应的Group条目,新增Group条目
			 */
			boolean flag = true;
			//3.2 找到域存在的节点
			String[] urllist = ldapGroupDN.split(",");
			int i = 0;
			while (flag) {
				flag = false;
				//域 中 都没有 将数组下标越界结束循环
				int index = ldapGroupDN.indexOf(urllist[i]+",");
				String newUrl = ldapGroupDN.substring(index+(urllist[i]+",").length(), ldapGroupDN.length());
				i++;
				try {
					Attributes attrs = dc.getAttributes(newUrl);
				} catch (Exception e2) {
					flag = true;
				}
			}
			//3.2.1 按照顺序以此增加 OU
			for(int j=i-1;j>=0;j--) {
				int index = ldapGroupDN.indexOf(urllist[j]+",");
				String newldapGroupDN = ldapGroupDN.substring(index, ldapGroupDN.length());
				String ou = urllist[j].substring(3);
				Attributes attrs = new BasicAttributes(); 
				HRADVo  HRADVo = (HRADVo) map.get("OU="+ou);
				//创建objectclass属性
				Attribute objclass = new BasicAttribute("objectclass");
				objclass.add("top");
				objclass.add("organizationalunit"); 
				//创建cn属性
				Attribute cn = new BasicAttribute("ou", ou); 
				Attribute name = new BasicAttribute("name", ou);
				attrs.put(name);
				attrs.put(objclass); 
				attrs.put(cn); 
				if(null != HRADVo.getName()) {
					//处理部门
					if("vno".equals(HRADVo.getVno())) {
						Attribute description = new BasicAttribute("description", HRADVo.getDef4()+"_" + HRADVo.getDef1().substring(0, HRADVo.getDef1().length()-1)); 
						attrs.put(description);
					}else {
						Attribute description = new BasicAttribute("description", HRADVo.getName()); 
						attrs.put(description);
					}
					
				}
				if(StringUtil.isNotBlank(HRADVo.getShortname())) {
					Attribute description = new BasicAttribute("displayName", HRADVo.getShortname()); 
					attrs.put(description);
				}
				
				//将属性绑定到新的条目上,创建该条目
				try {
					dc.bind(newldapGroupDN, null, attrs);
				} catch (NamingException e1) {
					return false;
				}
			}
		}
		return true;
    }

查询组织

	    public boolean getGroup(String ldapGroupDN) throws BusinessException{
    	try {
    		
			dc.getAttributes(ldapGroupDN);
			return true;
		} catch (NamingException e) {
			return false;
		}
    }

修改组织

    public void updateOU(String oldName,String newName) throws Exception{
        try {
            dc.rename(oldName, newName);
            Logger.info("修改成功!");
        } catch (Exception e) {
        	Logger.info("修改失败!");
        }
    }

删除人员

		@Override
	public boolean deleteUser(String userDN) throws BusinessException {
		try {
			dc.destroySubcontext(userDN);
        } catch (Exception e) {
        	return false;
        }
		return true;
	}

删除组织

	@Override
	public boolean deleteOU(String base) throws Exception {
		try {
			dc.removeFromEnvironment(base);
		}catch (Exception e) {
			return false;
		}
		return true;
	}

人员添加到岗位组

	public boolean addUserToGroup(String username, String groupName)
	{
		ModificationItem[] mods = new ModificationItem[1];
		Attribute member = new BasicAttribute("member",username);
		mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, member);
		try {
			dc.modifyAttributes(groupName, mods);
		} catch (NamingException e) {
			return false;
		}
		return true;
		
	}

人员从岗位组删除

	public boolean deleteUserFromGroup(String username, String groupName)
	{
		ModificationItem[] mods = new ModificationItem[1];
		Attribute attribute = new BasicAttribute("member",username);
		mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attribute);
		try {
			dc.modifyAttributes(groupName, mods);
		} catch (NamingException e) {
			return false;
		}
		return true;
		
	}

新增岗位组

		 public boolean AddGroup(String post, String postDN,String postname)
	 {	
		Attributes attributes=new BasicAttributes();
		Attribute attribute=new BasicAttribute("objectClass");	
		Attribute cn = new BasicAttribute("cn", post); 
		Attribute sAMAccountName = new BasicAttribute("sAMAccountName", post);
		Attribute displayName = new BasicAttribute("displayName", post);
		Attribute description = new BasicAttribute("description", postname);
		attribute.add("group");
		attributes.put(attribute);	
		attributes.put("groupType","2");
		attributes.put(cn);
		attributes.put(sAMAccountName);
		attributes.put(displayName);
		attributes.put(description);
	
		try {
			dc.createSubcontext(postDN,attributes);
		} catch (NamingException e) {
			return false;
		}
		return true;
		 
	 }

获取域OU结构

由前面介绍域的架构就发现域的存储结构跟我们数据库不一样,mysql oracle dm 等都是以表的形式存储,设置父字段存储上级主键
例:组织表 org

pk_orgpk_fatherorg
1
22
33

我们这个就要根据操作对象的主键查询

SELECT
        code        ,
        name        
FROM
        org START
WITH pk_org = ? CONNECT BY PRIOR pk_fatherorg = pk_org

具体代码如下

	public HashMap getORGURL(String pk_org,String pk_dept) throws Exception {
		HashMap map = new HashMap();
		String url = "";
		StringBuffer post = new StringBuffer();
		try {
			if(StringUtil.isNotBlank(pk_org)) {
				ArrayList<HRADVo> orgList = getAdSqlUtil().getOrgCode(pk_org);
				for(int i =orgList.size()-1;i>=0;i--) {
					if(i==orgList.size()-1) {
						if(StringUtil.isNotBlank(orgList.get(i).getDef3())) {
							url = "OU="+orgList.get(i).getDef3()+",";
							map.put("OU="+orgList.get(i).getDef3(), orgList.get(i));
						}else {
							url = "OU="+orgList.get(i).getCode()+",";
							map.put("OU="+orgList.get(i).getCode(), orgList.get(i));
						}

					}else {
						if(StringUtil.isNotBlank(orgList.get(i).getDef3())) {
							String[] ul = url.split(",");
							url = ul[0]+"."+orgList.get(i).getDef3()+","+url;
							map.put(ul[0]+"."+orgList.get(i).getDef3(), orgList.get(i));
						}else {
							String[] ul = url.split(",");
							url = ul[0]+"."+orgList.get(i).getCode()+","+url;
							map.put(ul[0]+"."+orgList.get(i).getCode(), orgList.get(i));
						}

					}
					
				}
			}
			if(StringUtil.isNotBlank(pk_dept)) {
				ArrayList<HRADVo>  codeList = getAdSqlUtil().getDeptCode(pk_dept);
				for(int i =codeList.size()-1;i>=0;i--) {
					if(StringUtil.isNotBlank(codeList.get(i).getShortname())) {
						post.append(codeList.get(i).getShortname()+"_");
						 codeList.get(i).setDef1(post.toString());
					}else if(StringUtil.isNotBlank(codeList.get(i).getName())){
						post.append(codeList.get(i).getName()+"_");
						codeList.get(i).setDef1(post.toString());
					}
					if(StringUtil.isNotBlank(codeList.get(i).getDef3())) {
						String[] ul = url.split(",");
						url = ul[0]+"."+codeList.get(i).getDef3()+","+url;
						map.put(ul[0]+"."+codeList.get(i).getDef3(), codeList.get(i));
					}else {
						String[] ul = url.split(",");
						url = ul[0]+"."+codeList.get(i).getCode()+","+url;
						map.put(ul[0]+"."+codeList.get(i).getCode(), codeList.get(i));
					}

				}
			}
			map.put("url", url);
			map.put("post", post);
		} catch (Exception e) {
			throw new Exception(e);
		}
		
		return map;
	}

根据这种方式就可以获得OU=100.27.04,OU=100.27,OU=100,这样的结构,在读取配置文件中域的地址(OU=wall,DC=gwtest,DC=com,DC=cn)就可以获取对应域中的OU地址

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值