mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-13 14:57:16 +08:00
feat: 新增密码策略-密码重复使用规则
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.continew.admin.system.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import top.continew.starter.data.mybatis.plus.base.BaseMapper;
|
||||||
|
import top.continew.admin.system.model.entity.UserPasswordHistoryDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户历史密码 Mapper
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2024/5/16 21:58
|
||||||
|
*/
|
||||||
|
public interface UserPasswordHistoryMapper extends BaseMapper<UserPasswordHistoryDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除过期历史密码
|
||||||
|
*
|
||||||
|
* @param userId 用户 ID
|
||||||
|
* @param count 保留 N 个历史
|
||||||
|
*/
|
||||||
|
void deleteExpired(@Param("userId") Long userId, @Param("count") int count);
|
||||||
|
}
|
@@ -17,8 +17,6 @@
|
|||||||
package top.continew.admin.system.model.entity;
|
package top.continew.admin.system.model.entity;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.dromara.x.file.storage.core.FileInfo;
|
import org.dromara.x.file.storage.core.FileInfo;
|
||||||
@@ -43,9 +41,6 @@ public class FileDO extends BaseDO {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_ID)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 名称
|
* 名称
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.continew.admin.system.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户历史密码实体
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2024/5/16 21:58
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("sys_user_password_history")
|
||||||
|
public class UserPasswordHistoryDO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户 ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
public UserPasswordHistoryDO(Long userId, String password) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
}
|
@@ -31,7 +31,7 @@ public interface RoleDeptService {
|
|||||||
*
|
*
|
||||||
* @param deptIds 部门 ID 列表
|
* @param deptIds 部门 ID 列表
|
||||||
* @param roleId 角色 ID
|
* @param roleId 角色 ID
|
||||||
* @return true:成功;false:无变更/失败
|
* @return 是否新增成功(true:成功;false:无变更/失败)
|
||||||
*/
|
*/
|
||||||
boolean add(List<Long> deptIds, Long roleId);
|
boolean add(List<Long> deptIds, Long roleId);
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ public interface RoleMenuService {
|
|||||||
*
|
*
|
||||||
* @param menuIds 菜单 ID 列表
|
* @param menuIds 菜单 ID 列表
|
||||||
* @param roleId 角色 ID
|
* @param roleId 角色 ID
|
||||||
* @return true:成功;false:无变更/失败
|
* @return 是否新增成功(true:成功;false:无变更/失败)
|
||||||
*/
|
*/
|
||||||
boolean add(List<Long> menuIds, Long roleId);
|
boolean add(List<Long> menuIds, Long roleId);
|
||||||
|
|
||||||
|
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.continew.admin.system.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户历史密码业务接口
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2024/5/16 21:58
|
||||||
|
*/
|
||||||
|
public interface UserPasswordHistoryService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
*
|
||||||
|
* @param userId 用户 ID
|
||||||
|
* @param password 密码
|
||||||
|
* @param count 保留 N 个历史
|
||||||
|
*/
|
||||||
|
void add(Long userId, String password, int count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码是否为重复使用
|
||||||
|
*
|
||||||
|
* @param userId 用户 ID
|
||||||
|
* @param password 密码
|
||||||
|
* @param count 最近 N 次
|
||||||
|
* @return 是否为重复使用
|
||||||
|
*/
|
||||||
|
boolean isPasswordReused(Long userId, String password, int count);
|
||||||
|
}
|
@@ -31,7 +31,7 @@ public interface UserRoleService {
|
|||||||
*
|
*
|
||||||
* @param roleIds 角色 ID 列表
|
* @param roleIds 角色 ID 列表
|
||||||
* @param userId 用户 ID
|
* @param userId 用户 ID
|
||||||
* @return true:成功;false:无变更/失败
|
* @return 是否新增成功(true:成功;false:无变更/失败)
|
||||||
*/
|
*/
|
||||||
boolean add(List<Long> roleIds, Long userId);
|
boolean add(List<Long> roleIds, Long userId);
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public interface UserRoleService {
|
|||||||
* 根据角色 ID 判断是否已被用户关联
|
* 根据角色 ID 判断是否已被用户关联
|
||||||
*
|
*
|
||||||
* @param roleIds 角色 ID 列表
|
* @param roleIds 角色 ID 列表
|
||||||
* @return true:已关联;false:未关联
|
* @return 是否已关联(true:已关联;false:未关联)
|
||||||
*/
|
*/
|
||||||
boolean isRoleIdExists(List<Long> roleIds);
|
boolean isRoleIdExists(List<Long> roleIds);
|
||||||
}
|
}
|
@@ -145,5 +145,5 @@ public interface UserService extends BaseService<UserResp, UserDetailResp, UserQ
|
|||||||
* @param pwdResetTime 上次重置密码时间
|
* @param pwdResetTime 上次重置密码时间
|
||||||
* @return 是否过期
|
* @return 是否过期
|
||||||
*/
|
*/
|
||||||
Boolean isPasswordExpired(LocalDateTime pwdResetTime);
|
boolean isPasswordExpired(LocalDateTime pwdResetTime);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.continew.admin.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import top.continew.admin.system.mapper.UserPasswordHistoryMapper;
|
||||||
|
import top.continew.admin.system.model.entity.UserPasswordHistoryDO;
|
||||||
|
import top.continew.admin.system.service.UserPasswordHistoryService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户历史密码业务实现
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2024/5/16 21:58
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserPasswordHistoryServiceImpl implements UserPasswordHistoryService {
|
||||||
|
|
||||||
|
private final UserPasswordHistoryMapper baseMapper;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void add(Long userId, String password, int count) {
|
||||||
|
baseMapper.insert(new UserPasswordHistoryDO(userId, password));
|
||||||
|
// 删除过期历史密码
|
||||||
|
baseMapper.deleteExpired(userId, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPasswordReused(Long userId, String password, int count) {
|
||||||
|
// 查询近 N 个历史密码
|
||||||
|
List<UserPasswordHistoryDO> list = baseMapper.lambdaQuery()
|
||||||
|
.select(UserPasswordHistoryDO::getPassword)
|
||||||
|
.eq(UserPasswordHistoryDO::getUserId, userId)
|
||||||
|
.orderByDesc(UserPasswordHistoryDO::getCreateTime)
|
||||||
|
.last("LIMIT %s".formatted(count))
|
||||||
|
.list();
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 校验是否重复使用历史密码
|
||||||
|
List<String> passwordList = list.stream().map(UserPasswordHistoryDO::getPassword).toList();
|
||||||
|
return passwordList.stream().anyMatch(p -> passwordEncoder.matches(password, p));
|
||||||
|
}
|
||||||
|
}
|
@@ -88,6 +88,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
private final FileStorageService fileStorageService;
|
private final FileStorageService fileStorageService;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final OptionService optionService;
|
private final OptionService optionService;
|
||||||
|
private final UserPasswordHistoryService userPasswordHistoryService;
|
||||||
@Resource
|
@Resource
|
||||||
private DeptService deptService;
|
private DeptService deptService;
|
||||||
@Value("${avatar.support-suffix}")
|
@Value("${avatar.support-suffix}")
|
||||||
@@ -192,6 +193,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updatePassword(String oldPassword, String newPassword, Long id) {
|
public void updatePassword(String oldPassword, String newPassword, Long id) {
|
||||||
CheckUtils.throwIfEqual(newPassword, oldPassword, "新密码不能与当前密码相同");
|
CheckUtils.throwIfEqual(newPassword, oldPassword, "新密码不能与当前密码相同");
|
||||||
UserDO user = super.getById(id);
|
UserDO user = super.getById(id);
|
||||||
@@ -200,16 +202,17 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
CheckUtils.throwIf(!passwordEncoder.matches(oldPassword, password), "当前密码错误");
|
CheckUtils.throwIf(!passwordEncoder.matches(oldPassword, password), "当前密码错误");
|
||||||
}
|
}
|
||||||
// 校验密码合法性
|
// 校验密码合法性
|
||||||
this.checkPassword(newPassword, user);
|
int passwordReusePolicy = this.checkPassword(newPassword, user);
|
||||||
// 更新密码和密码重置时间
|
// 更新密码和密码重置时间
|
||||||
user.setPassword(newPassword);
|
user.setPassword(newPassword);
|
||||||
user.setPwdResetTime(LocalDateTime.now());
|
user.setPwdResetTime(LocalDateTime.now());
|
||||||
baseMapper.updateById(user);
|
baseMapper.updateById(user);
|
||||||
onlineUserService.cleanByUserId(user.getId());
|
// 保存历史密码
|
||||||
|
userPasswordHistoryService.add(id, password, passwordReusePolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean isPasswordExpired(LocalDateTime pwdResetTime) {
|
public boolean isPasswordExpired(LocalDateTime pwdResetTime) {
|
||||||
// 永久有效
|
// 永久有效
|
||||||
int passwordExpirationDays = optionService.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name());
|
int passwordExpirationDays = optionService.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name());
|
||||||
if (passwordExpirationDays <= SysConstants.NO) {
|
if (passwordExpirationDays <= SysConstants.NO) {
|
||||||
@@ -343,7 +346,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
* @param password 密码
|
* @param password 密码
|
||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
*/
|
*/
|
||||||
private void checkPassword(String password, UserDO user) {
|
private int checkPassword(String password, UserDO user) {
|
||||||
// 密码最小长度
|
// 密码最小长度
|
||||||
int passwordMinLength = optionService.getValueByCode2Int(PASSWORD_MIN_LENGTH.name());
|
int passwordMinLength = optionService.getValueByCode2Int(PASSWORD_MIN_LENGTH.name());
|
||||||
ValidationUtils.throwIf(StrUtil.length(password) < passwordMinLength, PASSWORD_MIN_LENGTH.getDescription()
|
ValidationUtils.throwIf(StrUtil.length(password) < passwordMinLength, PASSWORD_MIN_LENGTH.getDescription()
|
||||||
@@ -362,6 +365,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
int passwordContainSpecialChar = optionService.getValueByCode2Int(PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name());
|
int passwordContainSpecialChar = optionService.getValueByCode2Int(PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name());
|
||||||
ValidationUtils.throwIf(passwordContainSpecialChar == SysConstants.YES && !ReUtil
|
ValidationUtils.throwIf(passwordContainSpecialChar == SysConstants.YES && !ReUtil
|
||||||
.isMatch(RegexConstants.SPECIAL_CHARACTER, password), PASSWORD_CONTAIN_SPECIAL_CHARACTERS.getDescription());
|
.isMatch(RegexConstants.SPECIAL_CHARACTER, password), PASSWORD_CONTAIN_SPECIAL_CHARACTERS.getDescription());
|
||||||
|
// 密码重复使用规则
|
||||||
|
int passwordReusePolicy = optionService.getValueByCode2Int(PASSWORD_REUSE_POLICY.name());
|
||||||
|
ValidationUtils.throwIf(userPasswordHistoryService.isPasswordReused(user
|
||||||
|
.getId(), password, passwordReusePolicy), PASSWORD_REUSE_POLICY.getDescription()
|
||||||
|
.formatted(passwordReusePolicy));
|
||||||
|
return passwordReusePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="top.continew.admin.system.mapper.UserPasswordHistoryMapper">
|
||||||
|
<delete id="deleteExpired">
|
||||||
|
DELETE FROM sys_user_password_history
|
||||||
|
WHERE id NOT IN (
|
||||||
|
SELECT * FROM (
|
||||||
|
SELECT id
|
||||||
|
FROM sys_user_password_history
|
||||||
|
WHERE user_id = #{userId}
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT #{count}
|
||||||
|
) t1
|
||||||
|
)
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
@@ -121,7 +121,7 @@ VALUES
|
|||||||
('密码有效期(天)', 'PASSWORD_EXPIRATION_DAYS', NULL, '0', '取值范围为 0-999(0 表示永久有效)。', NULL, NULL),
|
('密码有效期(天)', 'PASSWORD_EXPIRATION_DAYS', NULL, '0', '取值范围为 0-999(0 表示永久有效)。', NULL, NULL),
|
||||||
('密码重复使用规则', 'PASSWORD_REUSE_POLICY', NULL, '5', '不允许使用最近 N 次密码,取值范围为 3-32。', NULL, NULL),
|
('密码重复使用规则', 'PASSWORD_REUSE_POLICY', NULL, '5', '不允许使用最近 N 次密码,取值范围为 3-32。', NULL, NULL),
|
||||||
('密码最小长度', 'PASSWORD_MIN_LENGTH', NULL, '8', '取值范围为 8-32。', NULL, NULL),
|
('密码最小长度', 'PASSWORD_MIN_LENGTH', NULL, '8', '取值范围为 8-32。', NULL, NULL),
|
||||||
('密码是否允许包含正反序账号名', 'PASSWORD_ALLOW_CONTAIN_USERNAME', NULL, '0', '', NULL, NULL),
|
('密码是否允许包含正反序账号名', 'PASSWORD_ALLOW_CONTAIN_USERNAME', NULL, '1', '', NULL, NULL),
|
||||||
('密码是否必须包含特殊字符', 'PASSWORD_CONTAIN_SPECIAL_CHARACTERS', NULL, '0', '', NULL, NULL);
|
('密码是否必须包含特殊字符', 'PASSWORD_CONTAIN_SPECIAL_CHARACTERS', NULL, '0', '', NULL, NULL);
|
||||||
|
|
||||||
-- 初始化默认字典
|
-- 初始化默认字典
|
||||||
|
@@ -95,6 +95,15 @@ CREATE TABLE IF NOT EXISTS `sys_user` (
|
|||||||
INDEX `idx_update_user`(`update_user`) USING BTREE
|
INDEX `idx_update_user`(`update_user`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `sys_user_password_history` (
|
||||||
|
`id` bigint(20) NOT NULL COMMENT 'ID',
|
||||||
|
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||||
|
`password` varchar(255) NOT NULL COMMENT '密码',
|
||||||
|
`create_time` datetime NOT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
INDEX `idx_user_id`(`user_id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户历史密码表';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sys_user_social` (
|
CREATE TABLE IF NOT EXISTS `sys_user_social` (
|
||||||
`source` varchar(255) NOT NULL COMMENT '来源',
|
`source` varchar(255) NOT NULL COMMENT '来源',
|
||||||
`open_id` varchar(255) NOT NULL COMMENT '开放ID',
|
`open_id` varchar(255) NOT NULL COMMENT '开放ID',
|
||||||
|
@@ -121,7 +121,7 @@ VALUES
|
|||||||
('密码有效期(天)', 'PASSWORD_EXPIRATION_DAYS', NULL, '0', '取值范围为 0-999(0 表示永久有效)。', NULL, NULL),
|
('密码有效期(天)', 'PASSWORD_EXPIRATION_DAYS', NULL, '0', '取值范围为 0-999(0 表示永久有效)。', NULL, NULL),
|
||||||
('密码重复使用规则', 'PASSWORD_REUSE_POLICY', NULL, '5', '不允许使用最近 N 次密码,取值范围为 3-32。', NULL, NULL),
|
('密码重复使用规则', 'PASSWORD_REUSE_POLICY', NULL, '5', '不允许使用最近 N 次密码,取值范围为 3-32。', NULL, NULL),
|
||||||
('密码最小长度', 'PASSWORD_MIN_LENGTH', NULL, '8', '取值范围为 8-32。', NULL, NULL),
|
('密码最小长度', 'PASSWORD_MIN_LENGTH', NULL, '8', '取值范围为 8-32。', NULL, NULL),
|
||||||
('密码是否允许包含正反序账号名', 'PASSWORD_ALLOW_CONTAIN_USERNAME', NULL, '0', '', NULL, NULL),
|
('密码是否允许包含正反序账号名', 'PASSWORD_ALLOW_CONTAIN_USERNAME', NULL, '1', '', NULL, NULL),
|
||||||
('密码是否必须包含特殊字符', 'PASSWORD_CONTAIN_SPECIAL_CHARACTERS', NULL, '0', '', NULL, NULL);
|
('密码是否必须包含特殊字符', 'PASSWORD_CONTAIN_SPECIAL_CHARACTERS', NULL, '0', '', NULL, NULL);
|
||||||
|
|
||||||
-- 初始化默认字典
|
-- 初始化默认字典
|
||||||
|
@@ -158,6 +158,20 @@ COMMENT ON COLUMN "sys_user"."update_user" IS '修改人';
|
|||||||
COMMENT ON COLUMN "sys_user"."update_time" IS '修改时间';
|
COMMENT ON COLUMN "sys_user"."update_time" IS '修改时间';
|
||||||
COMMENT ON TABLE "sys_user" IS '用户表';
|
COMMENT ON TABLE "sys_user" IS '用户表';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS "sys_user_password_history" (
|
||||||
|
"id" int8 NOT NULL,
|
||||||
|
"user_id" int8 NOT NULL,
|
||||||
|
"password" varchar(255) NOT NULL,
|
||||||
|
"create_time" timestamp NOT NULL,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
CREATE INDEX "idx_uph_user_id" ON "sys_user_password_history" ("user_id");
|
||||||
|
COMMENT ON COLUMN "sys_user_password_history"."id" IS 'ID';
|
||||||
|
COMMENT ON COLUMN "sys_user_password_history"."user_id" IS '用户ID';
|
||||||
|
COMMENT ON COLUMN "sys_user_password_history"."password" IS '密码';
|
||||||
|
COMMENT ON COLUMN "sys_user_password_history"."create_time" IS '创建时间';
|
||||||
|
COMMENT ON TABLE "sys_user_password_history" IS '用户历史密码表';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "sys_user_social" (
|
CREATE TABLE IF NOT EXISTS "sys_user_social" (
|
||||||
"source" varchar(255) NOT NULL,
|
"source" varchar(255) NOT NULL,
|
||||||
"open_id" varchar(255) NOT NULL,
|
"open_id" varchar(255) NOT NULL,
|
||||||
|
Reference in New Issue
Block a user