refactor: 支持LDAP登录
This commit is contained in:
@@ -163,6 +163,11 @@
|
|||||||
<artifactId>hutool-extra</artifactId> <!-- 邮件 -->
|
<artifactId>hutool-extra</artifactId> <!-- 邮件 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-ldap</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.agt.module.system.controller.admin.user.vo.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.ldap.odm.annotations.Attribute;
|
||||||
|
import org.springframework.ldap.odm.annotations.Entry;
|
||||||
|
import org.springframework.ldap.odm.annotations.Id;
|
||||||
|
|
||||||
|
import javax.naming.Name;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Entry(base = "ou=users", objectClasses = {"inetOrgPerson", "organizationalPerson", "person", "top"})
|
||||||
|
public class LdapUser {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Name dn;
|
||||||
|
|
||||||
|
@Attribute(name = "cn")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Attribute(name = "sn")
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
@Attribute(name = "userPassword")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Attribute(name = "mail")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Attribute(name = "gecos")
|
||||||
|
private String gecos;
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.agt.framework.common.enums.CommonStatusEnum;
|
import org.agt.framework.common.enums.CommonStatusEnum;
|
||||||
import org.agt.framework.common.enums.UserTypeEnum;
|
import org.agt.framework.common.enums.UserTypeEnum;
|
||||||
import org.agt.framework.common.util.monitor.TracerUtils;
|
import org.agt.framework.common.util.monitor.TracerUtils;
|
||||||
|
import org.agt.framework.common.util.object.BeanUtils;
|
||||||
import org.agt.framework.common.util.servlet.ServletUtils;
|
import org.agt.framework.common.util.servlet.ServletUtils;
|
||||||
import org.agt.framework.common.util.validation.ValidationUtils;
|
import org.agt.framework.common.util.validation.ValidationUtils;
|
||||||
import org.agt.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
import org.agt.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||||
@@ -19,7 +20,17 @@ import org.agt.module.system.api.sms.SmsCodeApi;
|
|||||||
import org.agt.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import org.agt.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import org.agt.module.system.api.social.dto.SocialUserBindReqDTO;
|
import org.agt.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||||
import org.agt.module.system.api.social.dto.SocialUserRespDTO;
|
import org.agt.module.system.api.social.dto.SocialUserRespDTO;
|
||||||
import org.agt.module.system.controller.admin.auth.vo.*;
|
import org.agt.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthLoginRespVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthResetPasswordByNameReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.auth.vo.CaptchaVerificationReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.user.vo.user.LdapUser;
|
||||||
|
import org.agt.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||||
import org.agt.module.system.convert.auth.AuthConvert;
|
import org.agt.module.system.convert.auth.AuthConvert;
|
||||||
import org.agt.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
import org.agt.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||||
import org.agt.module.system.dal.dataobject.user.AdminUserDO;
|
import org.agt.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
@@ -30,17 +41,29 @@ import org.agt.module.system.enums.sms.SmsSceneEnum;
|
|||||||
import org.agt.module.system.service.logger.LoginLogService;
|
import org.agt.module.system.service.logger.LoginLogService;
|
||||||
import org.agt.module.system.service.member.MemberService;
|
import org.agt.module.system.service.member.MemberService;
|
||||||
import org.agt.module.system.service.oauth2.OAuth2TokenService;
|
import org.agt.module.system.service.oauth2.OAuth2TokenService;
|
||||||
|
import org.agt.module.system.service.permission.PermissionService;
|
||||||
import org.agt.module.system.service.social.SocialUserService;
|
import org.agt.module.system.service.social.SocialUserService;
|
||||||
import org.agt.module.system.service.user.AdminUserService;
|
import org.agt.module.system.service.user.AdminUserService;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.ldap.core.LdapTemplate;
|
||||||
|
import org.springframework.ldap.query.LdapQuery;
|
||||||
|
import org.springframework.ldap.query.LdapQueryBuilder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static org.agt.framework.common.util.servlet.ServletUtils.getClientIP;
|
import static org.agt.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||||
import static org.agt.module.system.enums.ErrorCodeConstants.*;
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_DISABLED;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_REGISTER_CAPTCHA_CODE_ERROR;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_MOBILE_NOT_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth Service 实现类
|
* Auth Service 实现类
|
||||||
@@ -67,6 +90,10 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||||||
private CaptchaService captchaService;
|
private CaptchaService captchaService;
|
||||||
@Resource
|
@Resource
|
||||||
private SmsCodeApi smsCodeApi;
|
private SmsCodeApi smsCodeApi;
|
||||||
|
@Resource
|
||||||
|
private LdapTemplate ldapTemplate;
|
||||||
|
@Resource
|
||||||
|
private PermissionService permissionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码的开关,默认为 true
|
* 验证码的开关,默认为 true
|
||||||
@@ -96,13 +123,50 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AdminUserDO authenticateByLdap(String username, String password) {
|
||||||
|
|
||||||
|
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
|
||||||
|
LdapUser ldapUsers;
|
||||||
|
try {
|
||||||
|
LdapQuery query = LdapQueryBuilder.query()
|
||||||
|
.where("uid").is(username).or("mail").is(username);
|
||||||
|
ldapUsers = ldapTemplate.findOne(query, LdapUser.class);
|
||||||
|
ldapTemplate.authenticate(query, password);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("登录失败:{}", e.getMessage());
|
||||||
|
createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||||
|
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||||
|
}
|
||||||
|
if (ldapUsers == null) {
|
||||||
|
createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||||
|
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验账号是否存在
|
||||||
|
AdminUserDO user = userService.getUserByUsername(username);
|
||||||
|
if (user == null) {
|
||||||
|
UserSaveReqVO userSaveReqVO = new UserSaveReqVO();
|
||||||
|
userSaveReqVO.setUsername(username);
|
||||||
|
userSaveReqVO.setPassword(password);
|
||||||
|
userSaveReqVO.setNickname(ldapUsers.getGecos());
|
||||||
|
userSaveReqVO.setEmail(ldapUsers.getEmail());
|
||||||
|
Long userId = userService.createUser(userSaveReqVO);
|
||||||
|
permissionService.assignUserRole(userId, Set.of(3L));
|
||||||
|
user = BeanUtils.toBean(userSaveReqVO, AdminUserDO.class);
|
||||||
|
user.setId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
||||||
// 校验验证码
|
// 校验验证码
|
||||||
validateCaptcha(reqVO);
|
validateCaptcha(reqVO);
|
||||||
|
|
||||||
// 使用账号密码,进行登录
|
// 使用账号密码,进行登录
|
||||||
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
// AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||||
|
AdminUserDO user = authenticateByLdap(reqVO.getUsername(), reqVO.getPassword());
|
||||||
|
|
||||||
// 首次登录不返回token
|
// 首次登录不返回token
|
||||||
if (user.getLoginDate() == null) {
|
if (user.getLoginDate() == null) {
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.mzt.logapi.context.LogRecordContext;
|
||||||
|
import com.mzt.logapi.service.impl.DiffParseFunction;
|
||||||
|
import com.mzt.logapi.starter.annotation.LogRecord;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.ConstraintViolationException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.agt.framework.common.enums.CommonStatusEnum;
|
import org.agt.framework.common.enums.CommonStatusEnum;
|
||||||
import org.agt.framework.common.exception.ServiceException;
|
import org.agt.framework.common.exception.ServiceException;
|
||||||
import org.agt.framework.common.pojo.PageResult;
|
import org.agt.framework.common.pojo.PageResult;
|
||||||
@@ -15,6 +22,7 @@ import org.agt.module.infra.api.config.ConfigApi;
|
|||||||
import org.agt.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
import org.agt.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||||
import org.agt.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
import org.agt.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||||
import org.agt.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
import org.agt.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||||
|
import org.agt.module.system.controller.admin.user.vo.user.LdapUser;
|
||||||
import org.agt.module.system.controller.admin.user.vo.user.UserImportExcelVO;
|
import org.agt.module.system.controller.admin.user.vo.user.UserImportExcelVO;
|
||||||
import org.agt.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
import org.agt.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
||||||
import org.agt.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
import org.agt.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
||||||
@@ -31,26 +39,52 @@ import org.agt.module.system.service.dept.DeptService;
|
|||||||
import org.agt.module.system.service.dept.PostService;
|
import org.agt.module.system.service.dept.PostService;
|
||||||
import org.agt.module.system.service.permission.PermissionService;
|
import org.agt.module.system.service.permission.PermissionService;
|
||||||
import org.agt.module.system.service.tenant.TenantService;
|
import org.agt.module.system.service.tenant.TenantService;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import org.agt.module.system.util.ldap.SHA512CryptVerifier;
|
||||||
import com.mzt.logapi.context.LogRecordContext;
|
|
||||||
import com.mzt.logapi.service.impl.DiffParseFunction;
|
|
||||||
import com.mzt.logapi.starter.annotation.LogRecord;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.ConstraintViolationException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.ldap.core.LdapTemplate;
|
||||||
|
import org.springframework.ldap.query.LdapQuery;
|
||||||
|
import org.springframework.ldap.query.LdapQueryBuilder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.naming.directory.BasicAttribute;
|
||||||
|
import javax.naming.directory.DirContext;
|
||||||
|
import javax.naming.directory.ModificationItem;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static org.agt.framework.common.util.collection.CollectionUtils.*;
|
import static org.agt.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
import static org.agt.module.system.enums.ErrorCodeConstants.*;
|
import static org.agt.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static org.agt.module.system.enums.LogRecordConstants.*;
|
import static org.agt.framework.common.util.collection.CollectionUtils.singleton;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_COUNT_MAX;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_EMAIL_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_IMPORT_INIT_PASSWORD;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_IS_DISABLE;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_PASSWORD_FAILED;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_REGISTER_DISABLED;
|
||||||
|
import static org.agt.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_CREATE_SUB_TYPE;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_CREATE_SUCCESS;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_DELETE_SUB_TYPE;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_DELETE_SUCCESS;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_TYPE;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_PASSWORD_SUCCESS;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_SUB_TYPE;
|
||||||
|
import static org.agt.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_SUCCESS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台用户 Service 实现类
|
* 后台用户 Service 实现类
|
||||||
@@ -87,6 +121,8 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
private ConfigApi configApi;
|
private ConfigApi configApi;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoleMapper roleMapper;
|
private RoleMapper roleMapper;
|
||||||
|
@Resource
|
||||||
|
private LdapTemplate ldapTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@@ -199,11 +235,13 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
@Override
|
@Override
|
||||||
public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
|
public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
|
||||||
// 校验旧密码密码
|
// 校验旧密码密码
|
||||||
validateOldPassword(id, reqVO.getOldPassword());
|
AdminUserDO user = validateOldPassword(id, reqVO.getOldPassword());
|
||||||
// 执行更新
|
// 执行更新
|
||||||
AdminUserDO updateObj = new AdminUserDO().setId(id);
|
AdminUserDO updateObj = new AdminUserDO().setId(id);
|
||||||
updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码
|
updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码
|
||||||
userMapper.updateById(updateObj);
|
userMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
updateLdapPassword(user.getUsername(), reqVO.getNewPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,6 +257,8 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
updateObj.setPassword(encodePassword(password)); // 加密密码
|
updateObj.setPassword(encodePassword(password)); // 加密密码
|
||||||
userMapper.updateById(updateObj);
|
userMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
updateLdapPassword(user.getUsername(), password);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
LogRecordContext.putVariable("user", user);
|
LogRecordContext.putVariable("user", user);
|
||||||
LogRecordContext.putVariable("newPassword", updateObj.getPassword());
|
LogRecordContext.putVariable("newPassword", updateObj.getPassword());
|
||||||
@@ -235,6 +275,28 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
updateObj.setPassword(encodePassword(password)); // 加密密码
|
updateObj.setPassword(encodePassword(password)); // 加密密码
|
||||||
updateObj.setLoginDate(LocalDateTime.now());
|
updateObj.setLoginDate(LocalDateTime.now());
|
||||||
userMapper.updateById(updateObj);
|
userMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
updateLdapPassword(user.getUsername(), password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLdapPassword(String username, String password) {
|
||||||
|
try {
|
||||||
|
LdapQuery query = LdapQueryBuilder.query()
|
||||||
|
.where("uid").is(username).or("mail").is(username);
|
||||||
|
LdapUser ldapUsers = ldapTemplate.findOne(query, LdapUser.class);
|
||||||
|
|
||||||
|
password = SHA512CryptVerifier.generateHash(password, "OY7N5bGk");
|
||||||
|
// 创建修改操作
|
||||||
|
ModificationItem[] modificationItems = new ModificationItem[1];
|
||||||
|
modificationItems[0] = new ModificationItem(
|
||||||
|
DirContext.REPLACE_ATTRIBUTE,
|
||||||
|
new BasicAttribute("userPassword", password)
|
||||||
|
);
|
||||||
|
ldapTemplate.modifyAttributes(ldapUsers.getDn(), modificationItems);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw exception(USER_PASSWORD_FAILED, e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -462,11 +524,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验旧密码
|
* 校验旧密码
|
||||||
|
*
|
||||||
* @param id 用户 id
|
* @param id 用户 id
|
||||||
* @param oldPassword 旧密码
|
* @param oldPassword 旧密码
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void validateOldPassword(Long id, String oldPassword) {
|
AdminUserDO validateOldPassword(Long id, String oldPassword) {
|
||||||
AdminUserDO user = userMapper.selectById(id);
|
AdminUserDO user = userMapper.selectById(id);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw exception(USER_NOT_EXISTS);
|
throw exception(USER_NOT_EXISTS);
|
||||||
@@ -474,6 +537,17 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||||||
if (!isPasswordMatch(oldPassword, user.getPassword())) {
|
if (!isPasswordMatch(oldPassword, user.getPassword())) {
|
||||||
throw exception(USER_PASSWORD_FAILED);
|
throw exception(USER_PASSWORD_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String username = user.getUsername();
|
||||||
|
LdapQuery query = LdapQueryBuilder.query()
|
||||||
|
.where("uid").is(username).or("mail").is(username);
|
||||||
|
ldapTemplate.authenticate(query, oldPassword);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("密码校验失败:{}", e.getMessage());
|
||||||
|
throw exception(USER_PASSWORD_FAILED);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.agt.module.system.util.ldap;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.Sha2Crypt;
|
||||||
|
|
||||||
|
public class SHA512CryptVerifier {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证密码是否匹配SHA-512 Crypt哈希
|
||||||
|
* @param password 明文密码
|
||||||
|
* @param hash 完整的哈希字符串(包括{CRYPT}前缀)
|
||||||
|
* @return 匹配返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean verifyPassword(String password, String hash) {
|
||||||
|
// 去除{CRYPT}前缀(如果存在)
|
||||||
|
if (hash.startsWith("{CRYPT}")) {
|
||||||
|
hash = hash.substring(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 使用Apache Commons Codec的Sha2Crypt进行验证
|
||||||
|
String computedHash = Sha2Crypt.sha512Crypt(password.getBytes(), hash);
|
||||||
|
return computedHash.equals(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("验证失败: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成SHA-512 Crypt哈希
|
||||||
|
* @param password 明文密码
|
||||||
|
* @param salt 盐值(可选,如果为null则自动生成)
|
||||||
|
* @return 哈希值(包含{CRYPT}前缀)
|
||||||
|
*/
|
||||||
|
public static String generateHash(String password, String salt) {
|
||||||
|
String hash;
|
||||||
|
if (salt != null) {
|
||||||
|
hash = Sha2Crypt.sha512Crypt(password.getBytes(), "$6$" + salt);
|
||||||
|
} else {
|
||||||
|
hash = Sha2Crypt.sha512Crypt(password.getBytes());
|
||||||
|
}
|
||||||
|
return "{CRYPT}" + hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String storedHash = "{CRYPT}$6$OY7N5bGk$WF6pEJOYU1SEySOuvLxVBNo2MRMsNAX4PX9JnzgUTYfDzevl1/fruztCTM0mIuiAUb3eJ//DEYxzFABmOlIzm/";
|
||||||
|
String password = "test"; // 要验证的密码
|
||||||
|
|
||||||
|
// 验证密码
|
||||||
|
boolean isValid = verifyPassword(password, storedHash);
|
||||||
|
System.out.println("密码验证结果: " + isValid);
|
||||||
|
|
||||||
|
// 生成新哈希(使用相同盐值)
|
||||||
|
String newHash = generateHash(password, "OY7N5bGk");
|
||||||
|
System.out.println("生成的哈希: " + newHash);
|
||||||
|
System.out.println("哈希匹配: " + newHash.equals(storedHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -251,3 +251,10 @@ justauth:
|
|||||||
pf4j:
|
pf4j:
|
||||||
# pluginsDir: /tmp/
|
# pluginsDir: /tmp/
|
||||||
pluginsDir: ../plugins
|
pluginsDir: ../plugins
|
||||||
|
|
||||||
|
spring:
|
||||||
|
ldap:
|
||||||
|
urls: ldap://192.168.88.205
|
||||||
|
base: dc=agrandtech,dc=com
|
||||||
|
username: uid=root,cn=users,dc=agrandtech,dc=com
|
||||||
|
password: Tian7989!
|
||||||
Reference in New Issue
Block a user