feat: 密码强度校验/密码过期时间功能

This commit is contained in:
TsMask
2025-03-31 15:18:17 +08:00
parent 70c84e4950
commit 36aa32dc94
11 changed files with 293 additions and 40 deletions

View File

@@ -104,6 +104,7 @@ func (s Account) ByUsername(username, password string) (token.TokenInfo, error)
func (s Account) UpdateLoginDateAndIP(tokenInfo token.TokenInfo) bool {
user := s.sysUserService.FindById(tokenInfo.UserId)
user.Password = "" // 密码不更新
user.LoginCount += 1
user.LoginIp = tokenInfo.LoginIp
user.LoginTime = tokenInfo.LoginTime
return s.sysUserService.Update(user) > 0
@@ -144,6 +145,22 @@ func (s Account) passwordRetryCount(userName string) (string, int64, time.Durati
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
}
// passwordRetryCount 密码过期时间
func (s Account) PasswordExpireTime(loginCount, passwordUpdateTime int64) (bool, error) {
// 首次登录
forcePasswdChange := loginCount < 1
// 非首次登录,判断密码是否过期
if !forcePasswdChange {
alert, err := s.sysUserService.ValidatePasswordExpireTime(passwordUpdateTime)
if err != nil {
return alert, err
}
forcePasswdChange = alert
}
return forcePasswdChange, nil
}
// RoleAndMenuPerms 角色和菜单数据权限
func (s Account) RoleAndMenuPerms(userId int64, isSystemUser bool) ([]string, []string) {
if isSystemUser {

View File

@@ -1,10 +1,13 @@
package service
import (
"encoding/json"
"fmt"
"regexp"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/parse"
systemModel "be.ems/src/modules/system/model"
systemService "be.ems/src/modules/system/service"
@@ -90,3 +93,45 @@ func (s Register) registerRoleInit() []int64 {
func (s Register) registerPostInit() []int64 {
return []int64{}
}
// ValidatePasswordPolicy 判断密码策略强度
func (s Register) ValidatePasswordPolicy(password string, errLang string) (bool, string) {
passwordPolicyStr := s.sysConfigService.FindValueByKey("sys.user.passwordPolicy")
if passwordPolicyStr == "" {
// 未配置密码策略
return false, i18n.TKey(errLang, "config.sys.user.passwordPolicyNot")
}
var policy struct {
MinLength int `json:"minLength"`
SpecialChars int `json:"specialChars"`
Uppercase int `json:"uppercase"`
Lowercase int `json:"lowercase"`
}
err := json.Unmarshal([]byte(passwordPolicyStr), &policy)
if err != nil {
return false, err.Error()
}
errMsg := i18n.TTemplate(errLang, "sys.user.passwordPolicyError", map[string]any{
"minLength": policy.MinLength,
"specialChars": policy.SpecialChars,
"uppercase": policy.Uppercase,
"lowercase": policy.Lowercase,
})
specialChars := len(regexp.MustCompile(`[!@#$%^&*(),.?":{}|<>]`).FindAllString(password, -1))
if specialChars < policy.SpecialChars {
return false, errMsg
}
uppercase := len(regexp.MustCompile(`[A-Z]`).FindAllString(password, -1))
if uppercase < policy.Uppercase {
return false, errMsg
}
lowercase := len(regexp.MustCompile(`[a-z]`).FindAllString(password, -1))
if lowercase < policy.Lowercase {
return false, errMsg
}
return true, ""
}