70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
package main
|
||
|
||
import (
|
||
"log"
|
||
|
||
"golang.org/x/crypto/bcrypt"
|
||
)
|
||
|
||
// EncryptPassword 对明文密码进行 bcrypt 加密
|
||
// 输入:明文密码(string)
|
||
// 返回:加密后的哈希字符串(string)和可能的错误(error)
|
||
func EncryptPassword(plainPassword string) (string, error) {
|
||
passwordBytes := []byte(plainPassword)
|
||
// cost=12,生产环境推荐值
|
||
hashBytes, err := bcrypt.GenerateFromPassword(passwordBytes, 12)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return string(hashBytes), nil
|
||
}
|
||
|
||
// VerifyPassword 验证明文密码与哈希密码是否匹配(核心:替代“解密”)
|
||
// 输入:明文密码(用户登录时输入)、数据库存储的哈希密码
|
||
// 返回:是否匹配(bool)、错误(error)
|
||
func VerifyPassword(plainPassword, hashedPassword string) (bool, error) {
|
||
// 1. 转换为字节切片
|
||
plainBytes := []byte(plainPassword)
|
||
hashedBytes := []byte(hashedPassword)
|
||
|
||
// 2. 核心验证:bcrypt 自动提取哈希中的盐值,用同样算法加密明文后比对
|
||
// 注意:这里返回的 error 是“验证失败”或“算法异常”,不是解密错误
|
||
err := bcrypt.CompareHashAndPassword(hashedBytes, plainBytes)
|
||
if err == nil {
|
||
return true, nil // 匹配成功(密码正确)
|
||
} else if err == bcrypt.ErrMismatchedHashAndPassword {
|
||
return false, nil // 匹配失败(密码错误)
|
||
} else {
|
||
return false, err // 其他异常(如哈希格式错误、内存不足等)
|
||
}
|
||
}
|
||
|
||
// 示例使用
|
||
func main() {
|
||
// 明文密码
|
||
plainPwd := "admin"
|
||
|
||
// 加密
|
||
hashedPwd, err := EncryptPassword(plainPwd)
|
||
if err != nil {
|
||
log.Fatalf("密码加密失败: %v", err)
|
||
}
|
||
|
||
// 输出加密结果(可存储到数据库的 password 字段)
|
||
log.Printf("明文密码: %s\n加密后: %s", plainPwd, hashedPwd)
|
||
|
||
loginInputPwd := "admin" // 用户登录时输入的明文(正确)
|
||
// loginInputPwd := "wrong123" // 错误密码(测试用)
|
||
|
||
match, err := VerifyPassword(loginInputPwd, hashedPwd)
|
||
if err != nil {
|
||
log.Fatalf("验证异常: %v", err)
|
||
}
|
||
|
||
if match {
|
||
log.Println("验证成功!密码正确")
|
||
} else {
|
||
log.Println("验证失败!密码错误")
|
||
}
|
||
}
|