【发布时间】:2022-01-24 14:27:29
【问题描述】:
我试图在 Golang 的 Fiber Farmework 上构建登录系统,并使用 Mysql 作为数据库。 我可以轻松地散列我的密码,但无法比较给定密码和存储的密码是否相同 我用过
bcrypt.CompareHashAndPassword() 方法..虽然我给出了完全相同的密码,但它仍然给出了一个错误。 请帮帮我
功能
func hashAndSalt(password string) string {
pwd := []byte(password)
hash, err := bcrypt.GenerateFromPassword(pwd, 14)
if err != nil {
log.Println(err)
}
return string(hash)
}
func CheckHash(hpass string, pass string) error {
err := bcrypt.CompareHashAndPassword([]byte(hpass), []byte(pass))
if err != nil {
return err
}
return nil
}
用户和登录类型
type User struct {
gorm.Model
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
Username string `json:"username"`
Password string `json:"-"`
UserType string `json:"user_type"`
}
type Log struct {
Username string `json:"username"`
Password string `json:"password"`
}
创建用户功能很好用
func CreateUser(c *fiber.Ctx) error {
user := new(User)
if err := c.BodyParser(user); err != nil {
return c.Status(500).SendString(err.Error())
}
pass := user.Password
hashedPass := hashAndSalt(pass)
user.Password = hashedPass
DB.Create(&user)
return c.JSON(&user)
}
登录方法...问题在于哈希检查...
const jwt_secret = "Fahim'sAwesomeSecret"
func Login(c *fiber.Ctx) error {
type Log struct {
Username string `json:"username"`
Password string `json:"password"`
}
var body Log
if err := c.BodyParser(&body); err != nil {
fmt.Println(err.Error(), "yayy")
panic(err.Error())
}
username := body.Username
password := body.Password
var user User
DB.Where("username = ?", username).First(&user)
if username != user.Username {
return c.Status(200).SendString("User not Found , Maybe wrong Username")
}
err := CheckHash(user.Password, password)
if err != nil {
fmt.Println(err)
return c.Status(500).SendString("Wrong Password")
}
token := jwt.New(jwt.SigningMethodHS256)
claims := token.Claims.(jwt.MapClaims)
claims["sub"] = user.ID
claims["exp"] = time.Now().Add(time.Hour * 24 * 7)
s, err := token.SignedString([]byte(jwt_secret))
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
c.Cookie(&fiber.Cookie{
Name: "jwt",
Value: s,
Expires: time.Now().Add(7 * 24 * time.Hour),
HTTPOnly: true,
SameSite: "lax",
})
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"token": s,
"user": user,
})
}
这是我在终端中遇到的错误
crypto/bcrypt: hashedPassword is not the hash of the given password
我已经打印了“user.Password”,并给出了存储在数据库中的值。 那么问题出在哪里?
【问题讨论】:
-
这是一个关于 Fiber 的问题(如果是,请询问 Fiber 的作者),关于如何使用包 bcrypt(这看起来很合理),还是您希望进行代码审查?
-
将其记入minimal reproducible example 将有助于获得答案,尽管这样做可能会为您解答问题。
-
在您的数据库中,您将哈希存储为字符串,但您得到的是 [] 字节。在
CheckHash中,您只是将字符串转换为 []byte,但不以任何方式对其进行解码。如果您在存储期间的某个地方对其进行 base64 编码,那么您应该正确解码它,而不是仅仅将编码的字符串转换为字节 -
@caveman 我是否必须使用变量并执行类似的操作?" newVar := []byte(hpass)" 然后在函数中使用该变量?我试过了,但没有用,你能给我举个你刚才说的话的例子吗?
-
@caveman 我按照你说的过程解决了
标签: go hash bcrypt fibers go-fiber