package util import ( "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" "strings" "time" "golang.org/x/crypto/bcrypt" ) // HashPassword 使用bcrypt加密密码 func HashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", fmt.Errorf("failed to hash password: %w", err) } return string(bytes), nil } // CheckPassword 验证密码 func CheckPassword(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } // GenerateRandomString 生成随机字符串 func GenerateRandomString(n int) (string, error) { b := make([]byte, n) _, err := rand.Read(b) if err != nil { return "", err } return base64.URLEncoding.EncodeToString(b)[:n], nil } // GenerateVerificationToken 生成验证令牌 func GenerateVerificationToken() (string, error) { return GenerateRandomString(32) } // GeneratePasswordResetToken 生成密码重置令牌 func GeneratePasswordResetToken() (string, error) { token, err := GenerateRandomString(32) if err != nil { return "", err } // 添加时间戳防止重复 return fmt.Sprintf("%s_%d", token, time.Now().Unix()), nil } // NormalizePhone 标准化手机号格式 func NormalizePhone(phone string) string { // 移除所有非数字字符 phone = strings.Map(func(r rune) rune { if r >= '0' && r <= '9' { return r } return -1 }, phone) // 如果以0开头,去掉0 if strings.HasPrefix(phone, "0") { phone = phone[1:] } // 如果以86开头,去掉86 if strings.HasPrefix(phone, "86") { phone = phone[2:] } return phone } // ValidatePasswordStrength 验证密码强度 func ValidatePasswordStrength(password string) error { if len(password) < 8 { return fmt.Errorf("password must be at least 8 characters long") } var hasUpper, hasLower, hasDigit bool for _, char := range password { switch { case 'A' <= char && char <= 'Z': hasUpper = true case 'a' <= char && char <= 'z': hasLower = true case '0' <= char && char <= '9': hasDigit = true case strings.ContainsRune("!@#$%^&*()-_=+[]{}|;:,.<>?", char): _ = true } } // 至少包含大小写字母和数字 if !hasUpper || !hasLower || !hasDigit { return fmt.Errorf("password must contain uppercase letters, lowercase letters and numbers") } return nil } // GenerateSalt 生成盐值(如果需要自定义加密算法) func GenerateSalt() (string, error) { salt := make([]byte, 16) _, err := rand.Read(salt) if err != nil { return "", err } return base64.StdEncoding.EncodeToString(salt), nil } // HashPasswordWithSalt 使用盐值哈希密码 func HashPasswordWithSalt(password, salt string) string { hash := sha256.New() hash.Write([]byte(password + salt)) return fmt.Sprintf("%x", hash.Sum(nil)) }