mingyang-admin-iot-app/rpc/internal/util/password_utils.go

121 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))
}