LDAP学员同步

This commit is contained in:
xxx 2023-11-14 12:00:20 +08:00
parent 8c905c6552
commit 040dcdfaed
4 changed files with 172 additions and 109 deletions

View File

@ -23,14 +23,12 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import xyz.playedu.api.event.UserLoginEvent;
import xyz.playedu.common.domain.LdapUser;
import xyz.playedu.common.bus.LDAPBus;
import xyz.playedu.common.domain.User;
import xyz.playedu.common.exception.ServiceException;
import xyz.playedu.common.service.*;
import xyz.playedu.common.util.HelperUtil;
import xyz.playedu.common.util.IpUtil;
import xyz.playedu.common.util.RequestUtil;
import xyz.playedu.common.util.StringUtil;
import xyz.playedu.common.util.ldap.LdapTransformUser;
import java.util.HashMap;
@ -41,14 +39,10 @@ public class LoginBus {
@Autowired private FrontendAuthService authService;
@Autowired private DepartmentService departmentService;
@Autowired private LdapUserService ldapUserService;
@Autowired private UserService userService;
@Autowired private AppConfigService appConfigService;
@Autowired private LDAPBus ldapBus;
@Autowired private ApplicationContext ctx;
public HashMap<String, Object> tokenByUser(User user) {
@ -72,72 +66,7 @@ public class LoginBus {
@Transactional
public HashMap<String, Object> tokenByLdapTransformUser(LdapTransformUser ldapTransformUser)
throws ServiceException {
// LDAP用户的名字
String ldapUserName = ldapTransformUser.getCn();
// 将LDAP用户所属的部门同步到本地
Integer depId = departmentService.createWithChainList(ldapTransformUser.getOu());
Integer[] depIds = depId == 0 ? null : new Integer[] {depId};
// LDAP用户在本地的缓存记录
LdapUser ldapUser = ldapUserService.findByUUID(ldapTransformUser.getId());
User user;
// 计算将LDAP用户关联到本地users表的email字段值
String localUserEmail = ldapTransformUser.getUid();
if (StringUtil.isNotEmpty(ldapTransformUser.getEmail())) {
localUserEmail = ldapTransformUser.getEmail();
}
if (ldapUser == null) {
// 检测localUserEmail是否存在
if (userService.find(localUserEmail) != null) {
throw new ServiceException(String.format("已有其它账号在使用:%s", localUserEmail));
}
// LDAP用户数据缓存到本地
ldapUser = ldapUserService.store(ldapTransformUser);
// 创建本地user
user =
userService.createWithDepIds(
localUserEmail,
ldapUserName,
appConfigService.defaultAvatar(),
HelperUtil.randomString(20),
"",
depIds);
// 将LDAP缓存数据与本地user关联
ldapUserService.updateUserId(ldapUser.getId(), user.getId());
} else {
user = userService.find(ldapUser.getUserId());
// 账号修改[账号有可能是email也有可能是uid]
if (!localUserEmail.equals(user.getEmail())) {
// 检测localUserEmail是否存在
if (userService.find(localUserEmail) != null) {
throw new ServiceException(String.format("已有其它账号在使用:%s", localUserEmail));
}
userService.updateEmail(user.getId(), localUserEmail);
}
// ldap-email的变化
if (!ldapUser.getEmail().equals(ldapTransformUser.getEmail())) {
ldapUserService.updateEmail(ldapUser.getId(), ldapTransformUser.getEmail());
}
// ldap-uid的变化
if (!ldapUser.getUid().equals(ldapTransformUser.getUid())) {
ldapUserService.updateUid(ldapUser.getId(), ldapTransformUser.getUid());
}
// 名字同步修改
if (!ldapUserName.equals(ldapUser.getCn())) {
userService.updateName(user.getId(), ldapUserName);
ldapUserService.updateCN(ldapUser.getId(), ldapUserName);
}
// 部门修改同步
String newOU = String.join(",", ldapTransformUser.getOu());
if (!newOU.equals(ldapUser.getOu())) {
userService.updateDepId(user.getId(), depIds);
ldapUserService.updateOU(ldapUser.getId(), newOU);
}
}
User user = ldapBus.singleUserSync(ldapTransformUser, appConfigService.defaultAvatar());
return tokenByUser(user);
}
}

View File

@ -316,4 +316,13 @@ public class DepartmentController {
ldapBus.departmentSync();
return JsonResponse.success();
}
@BackendPermission(slug = BPermissionConstant.DEPARTMENT_CUD)
@PostMapping("/ldap-user-sync")
@Log(title = "部门-LDAP学员同步", businessType = BusinessTypeConstant.INSERT)
@SneakyThrows
public JsonResponse ldapUserSync() {
ldapBus.userSync();
return JsonResponse.success();
}
}

View File

@ -22,12 +22,15 @@ import org.springframework.stereotype.Component;
import xyz.playedu.common.domain.Department;
import xyz.playedu.common.domain.LdapDepartment;
import xyz.playedu.common.domain.LdapUser;
import xyz.playedu.common.domain.User;
import xyz.playedu.common.exception.NotFoundException;
import xyz.playedu.common.service.AppConfigService;
import xyz.playedu.common.service.DepartmentService;
import xyz.playedu.common.service.LdapDepartmentService;
import xyz.playedu.common.service.*;
import xyz.playedu.common.types.LdapConfig;
import xyz.playedu.common.util.HelperUtil;
import xyz.playedu.common.util.StringUtil;
import xyz.playedu.common.util.ldap.LdapTransformDepartment;
import xyz.playedu.common.util.ldap.LdapTransformUser;
import xyz.playedu.common.util.ldap.LdapUtil;
import java.util.HashMap;
@ -47,6 +50,10 @@ public class LDAPBus {
@Autowired private LdapDepartmentService ldapDepartmentService;
@Autowired private LdapUserService ldapUserService;
@Autowired private UserService userService;
public boolean enabledLDAP() {
return appConfigService.enabledLdapLogin();
}
@ -149,5 +156,104 @@ public class LDAPBus {
}
}
public void userSync() {}
public void userSync() throws NamingException {
LdapConfig ldapConfig = appConfigService.ldapConfig();
List<LdapTransformUser> userList =
LdapUtil.users(
ldapConfig.getUrl(),
ldapConfig.getAdminUser(),
ldapConfig.getAdminPass(),
ldapConfig.getBaseDN());
if (userList == null || userList.isEmpty()) {
return;
}
String defaultAvatar = appConfigService.defaultAvatar();
for (LdapTransformUser ldapTransformUser : userList) {
singleUserSync(ldapTransformUser, defaultAvatar);
}
}
public User singleUserSync(LdapTransformUser ldapTransformUser, String defaultAvatar) {
// LDAP用户的名字
String ldapUserName = ldapTransformUser.getCn();
// 将LDAP用户所属的部门同步到本地
Integer depId = departmentService.createWithChainList(ldapTransformUser.getOu());
Integer[] depIds = depId == 0 ? null : new Integer[] {depId};
// LDAP用户在本地的缓存记录
LdapUser ldapUser = ldapUserService.findByUUID(ldapTransformUser.getId());
User user;
// 计算将LDAP用户关联到本地users表的email字段值
String localUserEmail = ldapTransformUser.getUid();
if (StringUtil.isNotEmpty(ldapTransformUser.getEmail())) {
localUserEmail = ldapTransformUser.getEmail();
}
if (ldapUser == null) {
// 检测localUserEmail是否存在
if (userService.find(localUserEmail) != null) {
localUserEmail = HelperUtil.randomString(5) + "_" + localUserEmail;
}
// LDAP用户数据缓存到本地
ldapUser = ldapUserService.store(ldapTransformUser);
// 创建本地user
user =
userService.createWithDepIds(
localUserEmail,
ldapUserName,
defaultAvatar,
HelperUtil.randomString(10),
"",
depIds);
// 将LDAP缓存数据与本地user关联
ldapUserService.updateUserId(ldapUser.getId(), user.getId());
} else {
user = userService.find(ldapUser.getUserId());
if (user == null) {
user =
userService.createWithDepIds(
localUserEmail,
ldapUserName,
defaultAvatar,
HelperUtil.randomString(10),
"",
depIds);
}
// 账号修改[账号有可能是email也有可能是uid]
if (!localUserEmail.equals(user.getEmail())) {
// 检测localUserEmail是否存在
if (userService.find(localUserEmail) != null) {
localUserEmail = HelperUtil.randomString(5) + "_" + localUserEmail;
}
userService.updateEmail(user.getId(), localUserEmail);
}
// ldap-email的变化
if (!ldapUser.getEmail().equals(ldapTransformUser.getEmail())) {
ldapUserService.updateEmail(ldapUser.getId(), ldapTransformUser.getEmail());
}
// ldap-uid的变化
if (!ldapUser.getUid().equals(ldapTransformUser.getUid())) {
ldapUserService.updateUid(ldapUser.getId(), ldapTransformUser.getUid());
}
// 名字同步修改
if (!ldapUserName.equals(ldapUser.getCn())) {
userService.updateName(user.getId(), ldapUserName);
ldapUserService.updateCN(ldapUser.getId(), ldapUserName);
}
// 部门修改同步
String newOU = String.join(",", ldapTransformUser.getOu());
if (!newOU.equals(ldapUser.getOu())) {
userService.updateDepId(user.getId(), depIds);
ldapUserService.updateOU(ldapUser.getId(), newOU);
}
}
return user;
}
}

View File

@ -48,14 +48,11 @@ public class LdapUtil {
"entryUUID",
// Window AD 域的属性
"memberOf",
"name",
"userPrincipalName",
"departmentNumber",
"telephoneNumber",
"mobile",
"department",
"distinguishedName",
"sAMAccountName",
"displayName",
"uSNCreated", // AD域的唯一属性
// 公用属性
@ -76,8 +73,10 @@ public class LdapUtil {
return new InitialLdapContext(context, null);
}
public static List<HashMap<String, String>> users(LdapContext ldapContext, String baseDN)
throws NamingException {
public static List<LdapTransformUser> users(
String url, String adminUser, String adminPass, String baseDN) throws NamingException {
LdapContext ldapContext = initContext(url, adminUser, adminPass);
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(USER_RETURN_ATTRS);
@ -97,14 +96,14 @@ public class LdapUtil {
return null;
}
List<HashMap<String, String>> users = new ArrayList<>();
List<LdapTransformUser> users = new ArrayList<>();
while (result.hasMoreElements()) {
SearchResult item = result.nextElement();
if (item == null) {
continue;
}
Attributes attributes = item.getAttributes();
log.info("name={},attributes={}", item.getName(), attributes);
LdapTransformUser ldapTransformUser = parseTransformUser(item, baseDN);
users.add(ldapTransformUser);
}
return users;
@ -222,19 +221,51 @@ public class LdapUtil {
}
// 根据mail或uid查询出来的用户
SearchResult item = result.nextElement();
Attributes attributes = item.getAttributes();
LdapTransformUser ldapUser = parseTransformUser(result.nextElement(), baseDN);
if (ldapUser == null) {
log.info("LDAP-用户不存在");
return null;
}
// 使用用户dn+提交的密码去登录ldap系统
// 登录成功则意味着密码正确
// 登录失败则意味着密码错误
try {
ldapContext = initContext(url, ldapUser.getDn() + "," + baseDN, password);
return ldapUser;
} catch (Exception e) {
// 无法登录->密码错误
log.error("LDAP-登录失败", e);
return null;
} finally {
ldapContext.close();
}
}
private static LdapTransformUser parseTransformUser(SearchResult item, String baseDN)
throws NamingException {
Attributes attributes = item.getAttributes();
if (attributes == null) {
return null;
}
LdapTransformUser ldapUser = new LdapTransformUser();
ldapUser.setDn(item.getName());
// name解析
String displayName = (String) attributes.get("displayName").get();
if (StringUtil.isEmpty(displayName)) {
displayName = (String) attributes.get("cn").get();
}
ldapUser.setCn(displayName);
// 邮箱解析
String email =
attributes.get("mail") == null ? null : (String) attributes.get("mail").get();
if (email == null) {
email = attributes.get("email") == null ? null : (String) attributes.get("email").get();
}
LdapTransformUser ldapUser = new LdapTransformUser();
ldapUser.setDn(item.getName());
ldapUser.setEmail(email);
ldapUser.setCn((String) attributes.get("cn").get());
if (attributes.get("uSNCreated") != null) {
// Window AD域
@ -262,19 +293,7 @@ public class LdapUtil {
Collections.reverse(ou);
ldapUser.setOu(ou);
// 使用用户dn+提交的密码去登录ldap系统
// 登录成功则意味着密码正确
// 登录失败则意味着密码错误
try {
ldapContext = initContext(url, ldapUser.getDn() + "," + baseDN, password);
return ldapUser;
} catch (Exception e) {
// 无法登录->密码错误
log.error("LDAP-登录失败", e);
return null;
} finally {
ldapContext.close();
}
return ldapUser;
}
private static String baseDNOuScope(String baseDN) {
@ -288,7 +307,7 @@ public class LdapUtil {
return String.join(",", ouScopes);
}
public static void closeContext(LdapContext ldapCtx) {
private static void closeContext(LdapContext ldapCtx) {
if (ldapCtx == null) {
return;
}