package validation import ( "strconv" "unicode" ) // PasswordConfig 密码验证配置 type PasswordConfig struct { MinLength int // 最小长度 MaxLength int // 最大长度 RequireUpper bool // 需要大写字母 RequireLower bool // 需要小写字母 RequireDigit bool // 需要数字 RequireSpecial bool // 需要特殊字符 } // DefaultPasswordConfig 默认密码配置。 // // P1 #17:MaxLength 由 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, "" }