|
|
@@ -0,0 +1,257 @@
|
|
|
+package com.uas.eis.serviceImpl;
|
|
|
+
|
|
|
+import com.uas.eis.core.LdapConnectionManager;
|
|
|
+import com.uas.eis.core.config.ADConfig;
|
|
|
+import com.uas.eis.dao.BaseDao;
|
|
|
+import com.uas.eis.entity.HrOrg;
|
|
|
+import com.uas.eis.utils.StringUtil;
|
|
|
+import org.apache.directory.api.ldap.model.cursor.CursorException;
|
|
|
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
|
|
|
+import org.apache.directory.api.ldap.model.entry.*;
|
|
|
+import org.apache.directory.api.ldap.model.exception.LdapException;
|
|
|
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
|
|
|
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
|
|
|
+import org.apache.directory.api.ldap.model.message.SearchScope;
|
|
|
+import org.apache.directory.api.ldap.model.name.Rdn;
|
|
|
+import org.apache.directory.api.util.Strings;
|
|
|
+import org.apache.directory.ldap.client.api.LdapConnection;
|
|
|
+import org.apache.directory.api.ldap.model.name.Dn;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ADSyncService {
|
|
|
+
|
|
|
+ private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ @Lazy
|
|
|
+ private LdapConnectionManager ldapConnectionManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ADConfig adConfig;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private BaseDao baseDao;
|
|
|
+ @Autowired
|
|
|
+ private OrgService orgService;
|
|
|
+
|
|
|
+ public void addOrg(String ouName, LdapConnection connection) throws Exception {
|
|
|
+ if(connection==null || !connection.isConnected()){
|
|
|
+ connection=ldapConnectionManager.getConnection();
|
|
|
+ }
|
|
|
+ Dn dn = new Dn("OU=" + ouName + "," + adConfig.getBaseDn());
|
|
|
+ Entry entry = new DefaultEntry(
|
|
|
+ dn,
|
|
|
+ "objectClass: top",
|
|
|
+ "objectClass: organizationalUnit"
|
|
|
+ );
|
|
|
+ entry.add("description", "SE");
|
|
|
+ connection.add(entry);
|
|
|
+ }
|
|
|
+ public void deleteOrg(String ouName, LdapConnection connection) throws Exception {
|
|
|
+ Dn dn = new Dn("OU=" + ouName + "," + adConfig.getBaseDn());
|
|
|
+ /*connection.delete(dn);
|
|
|
+ // 1. 构建组织DN
|
|
|
+ Dn orgDn = new Dn("OU=" + ouName + "," + adConfig.getBaseDn());
|
|
|
+
|
|
|
+ // 2. 检查组织下是否存在用户
|
|
|
+ String userFilter = FilterBuilder.equal("objectClass", "user").toString();
|
|
|
+ List<Entry> userEntries = (List<Entry>) connection.search(
|
|
|
+ orgDn,
|
|
|
+ userFilter,
|
|
|
+ SearchScope.SUBTREE,
|
|
|
+ "dn"
|
|
|
+ );
|
|
|
+
|
|
|
+ // 3. 如果存在用户,抛出异常阻止删除
|
|
|
+ if (!userEntries.isEmpty()) {
|
|
|
+ logger.info("组织下存在{}个用户,无法删除: {}",userEntries.size(),ouName);
|
|
|
+ }
|
|
|
+ connection.*/
|
|
|
+ // 4. 不存在用户,执行删除
|
|
|
+ // connection.delete(orgDn);
|
|
|
+ }
|
|
|
+ public void updateOrg(String oldOUName,String newOuName, LdapConnection connection) throws Exception {
|
|
|
+ Dn dn = new Dn("OU=" + oldOUName + "," + adConfig.getBaseDn());
|
|
|
+ Rdn newRdn = new Rdn("OU=" + newOuName);
|
|
|
+ connection.rename(dn, newRdn, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addUser(String userName,String displayName, String ouName, String password) throws LdapException, UnsupportedEncodingException {
|
|
|
+ LdapConnection connection = ldapConnectionManager.getConnection();
|
|
|
+ Dn dn = new Dn("CN="+displayName+"," + ouName + "," + adConfig.getBaseDn());
|
|
|
+ Entry entry = new DefaultEntry(
|
|
|
+ dn,
|
|
|
+ "objectClass: top",
|
|
|
+ "objectClass: person",
|
|
|
+ "objectClass: organizationalPerson",
|
|
|
+ "objectClass: user",
|
|
|
+ "sAMAccountName: " + userName,
|
|
|
+ "userPrincipalName: " + userName + "@" + adConfig.getBaseDn().replace("DC=", "").replace(",", "."),
|
|
|
+ "userPassword: " + password
|
|
|
+ );
|
|
|
+ //处理中文写入异常问题
|
|
|
+ entry.add("cn",displayName);
|
|
|
+ entry.add("displayName",displayName);
|
|
|
+ entry.add("givenName", displayName.substring(0, 1));
|
|
|
+ entry.add("sn", displayName.substring(1));
|
|
|
+ connection.add(entry);
|
|
|
+ }
|
|
|
+ /* public void deleteUser(String userName, String ouName) throws Exception {
|
|
|
+ try (LdapConnection connection = new LdapNetworkConnection(adConfig.getUrl())) {
|
|
|
+ connection.bind(adConfig.getAdminDn(), adConfig.getAdminPassword());
|
|
|
+
|
|
|
+ Dn dn = new Dn("CN=" + userName + ",OU=" + ouName + "," + adConfig.getBaseDn());
|
|
|
+ connection.delete(dn);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public void deleteOrganizationalUnit(String ouName) throws Exception {
|
|
|
+ try (LdapConnection connection = new LdapNetworkConnection(adConfig.getUrl())) {
|
|
|
+ connection.bind(adConfig.getAdminDn(), adConfig.getAdminPassword());
|
|
|
+
|
|
|
+ Dn dn = new Dn("OU=" + ouName + "," + adConfig.getBaseDn());
|
|
|
+ connection.delete(dn);
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ public void deleteUser(String userName, String ouName) throws Exception {
|
|
|
+ LdapConnection connection = ldapConnectionManager.getConnection();
|
|
|
+ Dn dn = new Dn("CN=测试,OU=人力资源部,OU=经营班子,OU=董事会,OU=User,DC=si,DC=ad");
|
|
|
+ connection.delete(dn);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void syncOrg() throws IOException {
|
|
|
+ LdapConnection connection = ldapConnectionManager.getConnection();
|
|
|
+ List<HrOrg> orgList = orgService.getOrgList();
|
|
|
+ logger.info("同步组织数量:{}",orgList.size());
|
|
|
+ List<String> orgDns = getOrganizations(connection);
|
|
|
+ //判断组织是否存在
|
|
|
+ for (HrOrg org : orgList) {
|
|
|
+ if("已审核".equals(org.getOr_status())) {
|
|
|
+ if(!orgDns.isEmpty()){
|
|
|
+ Optional<String> optionalString = orgDns.stream().filter(dn->dn.startsWith(getOUPath(org.getOr_path()))).findFirst();
|
|
|
+ if (optionalString.isPresent()) {
|
|
|
+ String orgDn = optionalString.get();
|
|
|
+ System.out.println(orgDn);
|
|
|
+ String orgDescription = orgDn.substring(orgDn.indexOf(";")+1);
|
|
|
+ if(!StringUtil.hasText(orgDescription)){
|
|
|
+
|
|
|
+ updateOrgDescription(orgDn.split(";")[0], org.getOr_code());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 修改自定义description属性
|
|
|
+ * */
|
|
|
+ public void updateOrgDescription(String orgName, String newDescription) throws IOException {
|
|
|
+ LdapConnection connection = null;
|
|
|
+ try {
|
|
|
+ connection = ldapConnectionManager.getConnection();
|
|
|
+ Dn dn = new Dn( orgName);
|
|
|
+ Entry entry = new DefaultEntry(
|
|
|
+ dn,
|
|
|
+ "objectClass: top",
|
|
|
+ "objectClass: organizationalUnit"
|
|
|
+ );
|
|
|
+ connection.modify(dn, new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "description", newDescription));
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.info("updateOrgDescription 更新组织描述失败:{}",e.getMessage());
|
|
|
+ }finally {
|
|
|
+ if (connection != null) {
|
|
|
+ connection.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 通过自定义description查看组织信息
|
|
|
+ * */
|
|
|
+ public List<String> findOrganizationsByDescription(String description) throws IOException {
|
|
|
+ LdapConnection connection = null;
|
|
|
+ try {
|
|
|
+ connection = ldapConnectionManager.getConnection();
|
|
|
+
|
|
|
+ // 设置LDAP搜索过滤器,匹配organizationalUnit且description包含搜索词
|
|
|
+ String filter = String.format("(&(objectClass=organizationalUnit)(description=*%s*))", description);
|
|
|
+ EntryCursor result = connection.search(
|
|
|
+ adConfig.getBaseDn(), // 从配置的基础DN开始搜索
|
|
|
+ filter,
|
|
|
+ SearchScope.SUBTREE, // 搜索所有子节点
|
|
|
+ "dn" // 只返回DN属性
|
|
|
+ );
|
|
|
+
|
|
|
+ List<String> orgDns = new ArrayList<>();
|
|
|
+ System.out.println(result.iterator().hasNext());
|
|
|
+ return orgDns;
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ if (connection != null) {
|
|
|
+ connection.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ private String getOUPath(String orpath){
|
|
|
+ String[] paths=orpath.split("-");
|
|
|
+ String ouPath="";
|
|
|
+ for(int i=paths.length-1;i>=0;i--){
|
|
|
+ ouPath+="OU="+paths[i]+",";
|
|
|
+ }
|
|
|
+ return ouPath.substring(0,ouPath.length()-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<String> getOrganizations(LdapConnection connection) throws IOException {
|
|
|
+ if(connection==null || !connection.isConnected()){
|
|
|
+ connection = ldapConnectionManager.getConnection();
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 搜索所有组织单元
|
|
|
+ List<String> orgDns = new ArrayList<>();
|
|
|
+ String filter = "(objectClass=organizationalUnit)";
|
|
|
+ EntryCursor result = connection.search(
|
|
|
+ "OU=User,"+adConfig.getBaseDn(), // AD基础DN,从配置文件获取
|
|
|
+ filter,
|
|
|
+ SearchScope.SUBTREE, // 搜索所有子节点
|
|
|
+ new String[] {"dn", "description"}
|
|
|
+ );
|
|
|
+ Entry entry = null;
|
|
|
+ while (result.next()) {
|
|
|
+ try {
|
|
|
+ entry =result.get();
|
|
|
+ System.out.println(entry.toString());
|
|
|
+ orgDns.add(String.format("%s;%s", entry.getDn().toString(),
|
|
|
+ StringUtil.hasText(entry.get("description"))?entry.get("description").toString():""));
|
|
|
+
|
|
|
+ } catch (CursorException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return orgDns;
|
|
|
+ } catch (LdapException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (CursorException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } finally {
|
|
|
+ if (connection != null) {
|
|
|
+ connection.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|