mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-11-04 10:57:10 +08:00 
			
		
		
		
	refactor: 使用枚举方法优化部分密码策略校验
This commit is contained in:
		@@ -16,9 +16,16 @@
 | 
			
		||||
 | 
			
		||||
package top.continew.admin.system.enums;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ReUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.hutool.extra.spring.SpringUtil;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import top.continew.admin.common.constant.RegexConstants;
 | 
			
		||||
import top.continew.admin.common.constant.SysConstants;
 | 
			
		||||
import top.continew.admin.system.model.entity.UserDO;
 | 
			
		||||
import top.continew.admin.system.service.UserPasswordHistoryService;
 | 
			
		||||
import top.continew.starter.core.util.validate.ValidationUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 密码策略枚举
 | 
			
		||||
@@ -31,47 +38,110 @@ import top.continew.admin.common.constant.SysConstants;
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
public enum PasswordPolicyEnum {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录密码错误锁定账号的次数
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ERROR_LOCK_COUNT(null, SysConstants.NO, 10),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录密码错误锁定账号的时间(min)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ERROR_LOCK_MINUTES(null, 1, 1440),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码到期提前提示(天)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_EXPIRATION_WARNING_DAYS(null, SysConstants.NO, Integer.MAX_VALUE),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码有效期(天)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_EXPIRATION_DAYS(null, SysConstants.NO, 999),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码重复使用规则
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_REUSE_POLICY("不允许使用最近 %s 次的历史密码", 3, 32),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码最小长度
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_MIN_LENGTH("密码最小长度为 %s 个字符", 8, 32),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码是否允许包含正反序账号名
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ALLOW_CONTAIN_USERNAME("密码不允许包含正反序账号名", SysConstants.NO, SysConstants.YES),
 | 
			
		||||
    PASSWORD_MIN_LENGTH("密码最小长度为 %s 个字符", 8, 32) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            // 最小长度校验
 | 
			
		||||
            ValidationUtils.throwIf(StrUtil.length(password) < policyValue, this.getDescription()
 | 
			
		||||
                .formatted(policyValue));
 | 
			
		||||
            // 完整校验
 | 
			
		||||
            int passwordMaxLength = this.getMax();
 | 
			
		||||
            ValidationUtils.throwIf(!ReUtil.isMatch(RegexConstants.PASSWORD_TEMPLATE
 | 
			
		||||
                .formatted(policyValue, passwordMaxLength), password), "密码长度为 {}-{} 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字", policyValue, passwordMaxLength);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码是否必须包含特殊字符
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_CONTAIN_SPECIAL_CHARACTERS("密码必须包含特殊字符", SysConstants.NO, SysConstants.YES),;
 | 
			
		||||
    PASSWORD_CONTAIN_SPECIAL_CHARACTERS("密码必须包含特殊字符", SysConstants.NO, SysConstants.YES) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            ValidationUtils.throwIf(policyValue == SysConstants.YES && !ReUtil
 | 
			
		||||
                .isMatch(RegexConstants.SPECIAL_CHARACTER, password), this.getDescription());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码是否允许包含正反序账号名
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ALLOW_CONTAIN_USERNAME("密码不允许包含正反序账号名", SysConstants.NO, SysConstants.YES) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            if (policyValue <= SysConstants.NO) {
 | 
			
		||||
                String username = user.getUsername();
 | 
			
		||||
                ValidationUtils.throwIf(StrUtil.containsAnyIgnoreCase(password, username, StrUtil
 | 
			
		||||
                    .reverse(username)), this.getDescription());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码重复使用规则
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_REUSE_POLICY("不允许使用最近 %s 次的历史密码", 3, 32) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            UserPasswordHistoryService userPasswordHistoryService = SpringUtil
 | 
			
		||||
                .getBean(UserPasswordHistoryService.class);
 | 
			
		||||
            ValidationUtils.throwIf(userPasswordHistoryService.isPasswordReused(user
 | 
			
		||||
                .getId(), password, policyValue), this.getDescription().formatted(policyValue));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录密码错误锁定账号的次数
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ERROR_LOCK_COUNT(null, SysConstants.NO, 10) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            // 无需此处校验
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录密码错误锁定账号的时间(min)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_ERROR_LOCK_MINUTES(null, 1, 1440) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            // 无需此处校验
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码到期提前提示(天)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_EXPIRATION_WARNING_DAYS(null, SysConstants.NO, Integer.MAX_VALUE) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            // 无需此处校验
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码有效期(天)
 | 
			
		||||
     */
 | 
			
		||||
    PASSWORD_EXPIRATION_DAYS(null, SysConstants.NO, 999) {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void validate(String password, int policyValue, UserDO user) {
 | 
			
		||||
            // 无需此处校验
 | 
			
		||||
        }
 | 
			
		||||
    },;
 | 
			
		||||
 | 
			
		||||
    private final String description;
 | 
			
		||||
    private final Integer min;
 | 
			
		||||
    private final Integer max;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 校验
 | 
			
		||||
     *
 | 
			
		||||
     * @param password    密码
 | 
			
		||||
     * @param policyValue 策略值
 | 
			
		||||
     * @param user        用户信息
 | 
			
		||||
     */
 | 
			
		||||
    public abstract void validate(String password, int policyValue, UserDO user);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.io.file.FileNameUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.core.util.ReUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import com.alicp.jetcache.anno.CacheInvalidate;
 | 
			
		||||
import com.alicp.jetcache.anno.CacheType;
 | 
			
		||||
@@ -39,7 +38,6 @@ import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
import top.continew.admin.auth.service.OnlineUserService;
 | 
			
		||||
import top.continew.admin.common.constant.CacheConstants;
 | 
			
		||||
import top.continew.admin.common.constant.RegexConstants;
 | 
			
		||||
import top.continew.admin.common.constant.SysConstants;
 | 
			
		||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
 | 
			
		||||
import top.continew.admin.common.util.helper.LoginHelper;
 | 
			
		||||
@@ -56,7 +54,6 @@ import top.continew.admin.system.model.resp.UserResp;
 | 
			
		||||
import top.continew.admin.system.service.*;
 | 
			
		||||
import top.continew.starter.core.constant.StringConstants;
 | 
			
		||||
import top.continew.starter.core.util.validate.CheckUtils;
 | 
			
		||||
import top.continew.starter.core.util.validate.ValidationUtils;
 | 
			
		||||
import top.continew.starter.extension.crud.model.query.PageQuery;
 | 
			
		||||
import top.continew.starter.extension.crud.model.resp.PageResp;
 | 
			
		||||
import top.continew.starter.extension.crud.service.CommonUserService;
 | 
			
		||||
@@ -348,28 +345,16 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
 | 
			
		||||
     */
 | 
			
		||||
    private int checkPassword(String password, UserDO user) {
 | 
			
		||||
        // 密码最小长度
 | 
			
		||||
        int passwordMinLength = optionService.getValueByCode2Int(PASSWORD_MIN_LENGTH.name());
 | 
			
		||||
        ValidationUtils.throwIf(StrUtil.length(password) < passwordMinLength, PASSWORD_MIN_LENGTH.getDescription()
 | 
			
		||||
            .formatted(passwordMinLength));
 | 
			
		||||
        // 密码是否允许包含正反序账号名
 | 
			
		||||
        int passwordAllowContainUsername = optionService.getValueByCode2Int(PASSWORD_ALLOW_CONTAIN_USERNAME.name());
 | 
			
		||||
        if (passwordAllowContainUsername == SysConstants.NO) {
 | 
			
		||||
            String username = user.getUsername();
 | 
			
		||||
            ValidationUtils.throwIf(StrUtil.containsAnyIgnoreCase(password, username, StrUtil
 | 
			
		||||
                .reverse(username)), PASSWORD_ALLOW_CONTAIN_USERNAME.getDescription());
 | 
			
		||||
        }
 | 
			
		||||
        int passwordMaxLength = PASSWORD_MIN_LENGTH.getMax();
 | 
			
		||||
        ValidationUtils.throwIf(!ReUtil.isMatch(RegexConstants.PASSWORD_TEMPLATE
 | 
			
		||||
            .formatted(passwordMinLength, passwordMaxLength), password), "密码长度为 {}-{} 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字", passwordMinLength, passwordMaxLength);
 | 
			
		||||
        PASSWORD_MIN_LENGTH.validate(password, optionService.getValueByCode2Int(PASSWORD_MIN_LENGTH.name()), user);
 | 
			
		||||
        // 密码是否必须包含特殊字符
 | 
			
		||||
        int passwordContainSpecialChar = optionService.getValueByCode2Int(PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name());
 | 
			
		||||
        ValidationUtils.throwIf(passwordContainSpecialChar == SysConstants.YES && !ReUtil
 | 
			
		||||
            .isMatch(RegexConstants.SPECIAL_CHARACTER, password), PASSWORD_CONTAIN_SPECIAL_CHARACTERS.getDescription());
 | 
			
		||||
        PASSWORD_CONTAIN_SPECIAL_CHARACTERS.validate(password, optionService
 | 
			
		||||
            .getValueByCode2Int(PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name()), user);
 | 
			
		||||
        // 密码是否允许包含正反序账号名
 | 
			
		||||
        PASSWORD_ALLOW_CONTAIN_USERNAME.validate(password, optionService
 | 
			
		||||
            .getValueByCode2Int(PASSWORD_ALLOW_CONTAIN_USERNAME.name()), user);
 | 
			
		||||
        // 密码重复使用规则
 | 
			
		||||
        int passwordReusePolicy = optionService.getValueByCode2Int(PASSWORD_REUSE_POLICY.name());
 | 
			
		||||
        ValidationUtils.throwIf(userPasswordHistoryService.isPasswordReused(user
 | 
			
		||||
            .getId(), password, passwordReusePolicy), PASSWORD_REUSE_POLICY.getDescription()
 | 
			
		||||
                .formatted(passwordReusePolicy));
 | 
			
		||||
        PASSWORD_REUSE_POLICY.validate(password, passwordReusePolicy, user);
 | 
			
		||||
        return passwordReusePolicy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user