feat: 密码不允许使用最近修改的密码功能

This commit is contained in:
TsMask
2025-03-31 18:31:25 +08:00
parent 15baf77ad3
commit 46b66cda5b
5 changed files with 194 additions and 19 deletions

View File

@@ -237,6 +237,13 @@ func (s *SysProfileController) PasswordUpdate(c *gin.Context) {
return
}
// 检查密码是否与历史密码一致
err = s.sysUserService.ValidatePasswordNotAllowedHistory(userInfo.UserId, body.NewPassword)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
// 修改新密码
userInfo.Password = body.NewPassword
userInfo.UpdateBy = userInfo.UserName
@@ -296,6 +303,13 @@ func (s *SysProfileController) PasswordForce(c *gin.Context) {
return
}
// 检查密码是否与历史密码一致
err = s.sysUserService.ValidatePasswordNotAllowedHistory(userInfo.UserId, body.Password)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
userInfo.Password = body.Password
userInfo.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.sysUserService.Update(userInfo)

View File

@@ -0,0 +1,16 @@
package model
// SysLogUserPassword 系统_用户密码变更日志表
type SysLogUserPassword struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // ID
UserId int64 `json:"userId" gorm:"column:user_id"` // 用户ID
UserName string `json:"userName" gorm:"column:user_name"` // 用户账号
Password string `json:"password" gorm:"column:password"` // 密码
CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者
CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间
}
// TableName 表名称
func (*SysLogUserPassword) TableName() string {
return "sys_log_user_password"
}

View File

@@ -0,0 +1,79 @@
package repository
import (
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/system/model"
)
// NewSysLogUserPassword 实例化数据层
var NewSysLogUserPassword = &SysLogUserPassword{}
// SysLogUserPasswordRepository 系统_用户密码变更日志表 数据层处理
type SysLogUserPassword struct{}
// SelectByUserId 通过用户ID日志 pageNum为0返回日志列表
func (r SysLogUserPassword) SelectByUserId(userId int64, pageNum int) []model.SysLogUserPassword {
rows := []model.SysLogUserPassword{}
if userId <= 0 {
return rows
}
tx := db.DB("").Model(&model.SysLogUserPassword{})
// 构建查询条件
tx = tx.Where("user_id = ?", userId)
// 查询数据分页
if pageNum > 0 {
tx = tx.Limit(pageNum)
}
err := tx.Order("create_time desc").Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectCountByUserId 通过用户ID日志数量
func (r SysLogUserPassword) SelectCountByUserId(userId int64) int64 {
var total int64 = 0
if userId <= 0 {
return total
}
tx := db.DB("").Model(&model.SysLogUserPassword{})
// 构建查询条件
tx = tx.Where("user_id = ?", userId)
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return total
}
return total
}
// Insert 新增信息 返回新增的数据ID
func (r SysLogUserPassword) Insert(param model.SysLogUserPassword) int64 {
if param.CreateBy != "" {
param.CreateTime = time.Now().UnixMilli()
}
// 执行插入
if err := db.DB("").Create(&param).Error; err != nil {
logger.Errorf("insert err => %v", err.Error())
return 0
}
return param.ID
}
// DeleteByUserId 删除用户日志信息 返回受影响行数
func (r SysLogUserPassword) DeleteByUserId(userIds []int64) int64 {
if len(userIds) <= 0 {
return 0
}
tx := db.DB("").Where("user_id in ?", userIds)
// 执行删除
if err := tx.Delete(&model.SysLogUserPassword{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}

View File

@@ -0,0 +1,26 @@
package service
import (
"be.ems/src/modules/system/model"
"be.ems/src/modules/system/repository"
)
// NewSysLogUserPassword 实例化服务层
var NewSysLogUserPassword = &SysLogUserPassword{
sysLogUserPasswordRepository: repository.NewSysLogUserPassword,
}
// SysLogUserPassword 用户密码变更日志 服务层处理
type SysLogUserPassword struct {
sysLogUserPasswordRepository *repository.SysLogUserPassword // 用户密码变更日志表日志信息
}
// Insert 新增信息
func (s SysLogUserPassword) Insert(param model.SysLogUserPassword) int64 {
return s.sysLogUserPasswordRepository.Insert(param)
}
// Delete 删除信息
func (s SysLogUserPassword) DeleteByUserId(userIds []int64) int64 {
return s.sysLogUserPasswordRepository.DeleteByUserId(userIds)
}

View File

@@ -8,32 +8,36 @@ import (
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/crypto"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/system/model"
"be.ems/src/modules/system/repository"
)
// NewSysUser 实例化服务层
var NewSysUser = &SysUser{
sysUserRepository: repository.NewSysUser,
sysRoleRepository: repository.NewSysRole,
sysDeptRepository: repository.NewSysDept,
sysUserRoleRepository: repository.NewSysUserRole,
sysUserPostRepository: repository.NewSysUserPost,
sysDictTypeService: NewSysDictType,
sysDictDataService: NewSysDictData,
sysConfigService: NewSysConfig,
sysUserRepository: repository.NewSysUser,
sysRoleRepository: repository.NewSysRole,
sysDeptRepository: repository.NewSysDept,
sysUserRoleRepository: repository.NewSysUserRole,
sysUserPostRepository: repository.NewSysUserPost,
sysDictTypeService: NewSysDictType,
sysDictDataService: NewSysDictData,
sysConfigService: NewSysConfig,
sysLogUserPasswordService: NewSysLogUserPassword,
}
// SysUser 用户 服务层处理
type SysUser struct {
sysUserRepository *repository.SysUser // 用户服务
sysRoleRepository *repository.SysRole // 角色服务
sysDeptRepository *repository.SysDept // 部门服务
sysUserRoleRepository *repository.SysUserRole // 用户与角色服务
sysUserPostRepository *repository.SysUserPost // 用户与岗位服务
sysDictTypeService *SysDictType // 字典类型服务
sysDictDataService *SysDictData // 字典数据服务
sysConfigService *SysConfig // 参数配置服务
sysUserRepository *repository.SysUser // 用户服务
sysRoleRepository *repository.SysRole // 角色服务
sysDeptRepository *repository.SysDept // 部门服务
sysUserRoleRepository *repository.SysUserRole // 用户与角色服务
sysUserPostRepository *repository.SysUserPost // 用户与岗位服务
sysDictTypeService *SysDictType // 字典类型服务
sysDictDataService *SysDictData // 字典数据服务
sysConfigService *SysConfig // 参数配置服务
sysLogUserPasswordService *SysLogUserPassword // 用户密码变更日志服务
}
// FindByPage 分页查询列表数据
@@ -140,7 +144,17 @@ func (s SysUser) insertUserPost(userId int64, postIds []int64) int64 {
// Update 修改信息
func (s SysUser) Update(sysUser model.SysUser) int64 {
return s.sysUserRepository.Update(sysUser)
rows := s.sysUserRepository.Update(sysUser)
// 记录密码变更日志
if rows > 0 && sysUser.Password != "" {
s.sysLogUserPasswordService.Insert(model.SysLogUserPassword{
UserId: sysUser.UserId,
UserName: sysUser.UserName,
Password: crypto.BcryptHash(sysUser.Password),
CreateBy: sysUser.UpdateBy,
})
}
return rows
}
// UpdateUserAndRolePost 修改用户信息同时更新角色和岗位
@@ -164,8 +178,9 @@ func (s SysUser) DeleteByIds(userIds []int64) (int64, error) {
return 0, fmt.Errorf("没有权限访问用户数据!")
}
if len(users) == len(userIds) {
s.sysUserRoleRepository.DeleteByUserIds(userIds) // 删除用户与角色关联
s.sysUserPostRepository.DeleteByUserIds(userIds) // 删除用户与岗位关联
s.sysUserRoleRepository.DeleteByUserIds(userIds) // 删除用户与角色关联
s.sysUserPostRepository.DeleteByUserIds(userIds) // 删除用户与岗位关联
s.sysLogUserPasswordService.DeleteByUserId(userIds) // 删除用户密码变更日志
return s.sysUserRepository.DeleteByIds(userIds), nil
}
return 0, fmt.Errorf("删除用户信息失败!")
@@ -320,3 +335,28 @@ func (s SysUser) ValidatePasswordExpireTime(passwordUpdateTime int64) (bool, err
}
return alertFlag, nil
}
// ValidatePasswordNotAllowedHistory 密码不允许使用最近修改的
func (s SysUser) ValidatePasswordNotAllowedHistory(userId int64, password string) error {
passwdNotAllowedHistoryStr := s.sysConfigService.FindValueByKey("sys.user.passwdNotAllowedHistory")
if passwdNotAllowedHistoryStr == "" {
return nil
}
passwdNotAllowedHistory := parse.Number(passwdNotAllowedHistoryStr)
if passwdNotAllowedHistory <= 0 {
return nil
}
// 查询密码历史记录
rows := s.sysLogUserPasswordService.sysLogUserPasswordRepository.SelectByUserId(userId, int(passwdNotAllowedHistory))
if len(rows) <= 0 {
return nil
}
// 检查密码是否在历史记录中
for _, v := range rows {
compare := crypto.BcryptCompare(password, v.Password)
if compare {
return fmt.Errorf("login.errPasswdHistory")
}
}
return nil
}