项目文件夹

文件
2026-07-14 10:24:10 +08:00

90 行
2.5 KiB
Go

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
package validation
import (
"strconv"
"unicode"
)
// PasswordConfig 密码验证配置
type PasswordConfig struct {
MinLength int // 最小长度
MaxLength int // 最大长度
RequireUpper bool // 需要大写字母
RequireLower bool // 需要小写字母
RequireDigit bool // 需要数字
RequireSpecial bool // 需要特殊字符
}
// DefaultPasswordConfig 默认密码配置。
//
// P1 #17MaxLength 由 128 收敛到 72(字节)。bcrypt 在 72 字节处静默截断——
// 若允许更长密码,两个前 72 字节相同的不同密码会被视为同一密码通过认证。
// length 用 len()(字节)度量,与 bcrypt 的字节截断口径一致。需支持超长密码时,
// 应在哈希前先做 SHA-256 预哈希再交给 bcrypt,而非放宽此上限。
var DefaultPasswordConfig = PasswordConfig{
MinLength: 8, // 最少8位
MaxLength: 72, // 最多72字节(bcrypt 截断边界,见上)
RequireUpper: true,
RequireLower: true,
RequireDigit: true,
RequireSpecial: false,
}
// ValidatePassword 验证密码强度
// 返回:是否有效,错误信息
func ValidatePassword(password string) (bool, string) {
return ValidatePasswordWithConfig(password, DefaultPasswordConfig)
}
// ValidatePasswordWithConfig 使用指定配置验证密码强度
func ValidatePasswordWithConfig(password string, config PasswordConfig) (bool, string) {
length := len(password)
// 检查最小长度
if length < config.MinLength {
return false, "密码长度不能少于" + strconv.Itoa(config.MinLength) + "位"
}
// 检查最大长度
if length > config.MaxLength {
return false, "密码长度不能超过" + strconv.Itoa(config.MaxLength) + "位"
}
var hasUpper, hasLower, hasDigit, hasSpecial bool
for _, char := range password {
switch {
case unicode.IsUpper(char):
hasUpper = true
case unicode.IsLower(char):
hasLower = true
case unicode.IsDigit(char):
hasDigit = true
case unicode.IsPunct(char) || unicode.IsSymbol(char):
hasSpecial = true
}
}
// 检查大写字母
if config.RequireUpper && !hasUpper {
return false, "密码必须包含大写字母"
}
// 检查小写字母
if config.RequireLower && !hasLower {
return false, "密码必须包含小写字母"
}
// 检查数字
if config.RequireDigit && !hasDigit {
return false, "密码必须包含数字"
}
// 检查特殊字符
if config.RequireSpecial && !hasSpecial {
return false, "密码必须包含特殊字符"
}
return true, ""
}