LDAP用户分页读取

This commit is contained in:
xxx 2023-12-26 14:57:15 +08:00
parent ff9e212366
commit 8d03678e71
2 changed files with 71 additions and 40 deletions

View File

@ -33,6 +33,7 @@ import xyz.playedu.common.util.ldap.LdapTransformDepartment;
import xyz.playedu.common.util.ldap.LdapTransformUser; import xyz.playedu.common.util.ldap.LdapTransformUser;
import xyz.playedu.common.util.ldap.LdapUtil; import xyz.playedu.common.util.ldap.LdapUtil;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -162,7 +163,7 @@ public class LDAPBus {
} }
} }
public void userSync() throws NamingException { public void userSync() throws NamingException, IOException {
LdapConfig ldapConfig = appConfigService.ldapConfig(); LdapConfig ldapConfig = appConfigService.ldapConfig();
List<LdapTransformUser> userList = List<LdapTransformUser> userList =

View File

@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
import xyz.playedu.common.exception.ServiceException; import xyz.playedu.common.exception.ServiceException;
import xyz.playedu.common.util.StringUtil; import xyz.playedu.common.util.StringUtil;
import java.io.IOException;
import java.util.*; import java.util.*;
import javax.naming.Context; import javax.naming.Context;
@ -29,8 +30,7 @@ import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes; import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls; import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult; import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.*;
import javax.naming.ldap.LdapContext;
@Slf4j @Slf4j
public class LdapUtil { public class LdapUtil {
@ -41,25 +41,25 @@ public class LdapUtil {
"(|(objectClass=person)(objectClass=posixAccount)(objectClass=inetOrgPerson)(objectClass=organizationalPerson)(objectClass=user))"; "(|(objectClass=person)(objectClass=posixAccount)(objectClass=inetOrgPerson)(objectClass=organizationalPerson)(objectClass=user))";
private static final String[] USER_RETURN_ATTRS = private static final String[] USER_RETURN_ATTRS =
new String[] { new String[]{
// OpenLDAP 的属性 // OpenLDAP 的属性
"uid", // 用户的唯一识别符号全局唯一可以看做用户表的手机号此字段可用于配合密码直接登录 "uid", // 用户的唯一识别符号全局唯一可以看做用户表的手机号此字段可用于配合密码直接登录
"cn", // CommonName -> 可以认作为人的名字比如张三在LDAP中此字段是可以重复的,但是同一ou下不可重复 "cn", // CommonName -> 可以认作为人的名字比如张三在LDAP中此字段是可以重复的,但是同一ou下不可重复
"email", // 邮箱同上 "email", // 邮箱同上
"entryUUID", "entryUUID",
// Window AD 域的属性 // Window AD 域的属性
"name", "name",
"userPrincipalName", "userPrincipalName",
"distinguishedName", "distinguishedName",
"sAMAccountName", "sAMAccountName",
"displayName", "displayName",
"uSNCreated", // AD域的唯一属性 "uSNCreated", // AD域的唯一属性
// 公用属性 // 公用属性
"mail", "mail",
}; };
private static final String[] OU_RETURN_ATTRS = new String[] {"ou", "usncreated"}; private static final String[] OU_RETURN_ATTRS = new String[]{"ou", "usncreated"};
public static LdapContext initContext(String url, String adminUser, String adminPass) public static LdapContext initContext(String url, String adminUser, String adminPass)
throws NamingException { throws NamingException {
@ -75,41 +75,71 @@ public class LdapUtil {
} }
public static List<LdapTransformUser> users( public static List<LdapTransformUser> users(
String url, String adminUser, String adminPass, String baseDN) throws NamingException { String url, String adminUser, String adminPass, String baseDN) throws NamingException, IOException {
LdapContext ldapContext = initContext(url, adminUser, adminPass); LdapContext ldapContext = initContext(url, adminUser, adminPass);
int pageSize = 1000;
List<LdapTransformUser> users = new ArrayList<>();
SearchControls controls = new SearchControls(); SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE); controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(USER_RETURN_ATTRS); controls.setReturningAttributes(USER_RETURN_ATTRS);
controls.setReturningObjFlag(true); controls.setReturningObjFlag(true);
NamingEnumeration<SearchResult> result = null; byte[] cookie = null;
try {
result = ldapContext.search(baseDN, USER_OBJECT_CLASS, controls); while (true) {
} catch (NamingException e) { try {
log.error("LDAP用户查询失败", e); if (cookie != null) {
} finally { ldapContext.setRequestControls(new Control[]{
closeContext(ldapContext); new PagedResultsControl(pageSize, cookie, false),
});
} else {
ldapContext.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, false)
});
}
NamingEnumeration<SearchResult> result = ldapContext.search(baseDN, USER_OBJECT_CLASS, controls);
while (result.hasMoreElements()) {
SearchResult item = result.nextElement();
if (item != null) {
LdapTransformUser ldapTransformUser = parseTransformUser(item, baseDN);
users.add(ldapTransformUser);
}
}
cookie = parseCookie(ldapContext.getResponseControls());
if (cookie == null || cookie.length == 0) {
break;
}
} catch (NamingException e) {
log.error("LDAP用户查询失败", e);
break;
}
} }
if (result == null || !result.hasMoreElements()) { closeContext(ldapContext);
if (users.isEmpty()) {
log.info("LDAP服务中没有用户"); log.info("LDAP服务中没有用户");
return null; return null;
} }
List<LdapTransformUser> users = new ArrayList<>();
while (result.hasMoreElements()) {
SearchResult item = result.nextElement();
if (item == null) {
continue;
}
LdapTransformUser ldapTransformUser = parseTransformUser(item, baseDN);
users.add(ldapTransformUser);
}
return users; return users;
} }
private static byte[] parseCookie(Control[] controls) throws NamingException {
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
return ((PagedResultsResponseControl) control).getCookie();
}
}
}
return null;
}
public static List<LdapTransformDepartment> departments( public static List<LdapTransformDepartment> departments(
String url, String adminUser, String adminPass, String baseDN) throws NamingException { String url, String adminUser, String adminPass, String baseDN) throws NamingException {
LdapContext ldapContext = initContext(url, adminUser, adminPass); LdapContext ldapContext = initContext(url, adminUser, adminPass);
@ -281,8 +311,8 @@ public class LdapUtil {
String baseDNOuScope = baseDNOuScope(baseDN); String baseDNOuScope = baseDNOuScope(baseDN);
String[] rdnList = String[] rdnList =
(baseDNOuScope.isEmpty() (baseDNOuScope.isEmpty()
? ldapUser.getDn().toLowerCase() ? ldapUser.getDn().toLowerCase()
: ldapUser.getDn().toLowerCase() + "," + baseDNOuScope) : ldapUser.getDn().toLowerCase() + "," + baseDNOuScope)
.split(","); .split(",");
List<String> ou = new ArrayList<>(); List<String> ou = new ArrayList<>();
for (String s : rdnList) { for (String s : rdnList) {