英文:
error: crypto/bcrypt: hashedPassword is not the hash of the given password
问题
我正在为用户创建身份验证路由。当我创建用户时,我将密码保存为哈希值,并在身份验证中创建了以下函数来验证密码,使用了crypto/bcrypt库:
func (user *User) ValidatePassword(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
if err != nil {
println(user.Password, password)
panic(err)
}
return err == nil
}
保存用户时一切正常,但在进行身份验证时,密码验证返回以下错误:
// hashes compared
$2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa
// error
http: panic serving 127.0.0.1:62939: crypto/bcrypt: hashedPassword is not the hash of the given password
goroutine 20 [running]:
net/http.(*conn).serve.func1()
我创建了一个哈希并将其转换为字符串进行保存:
func NewUser(name, email, password string) (*User, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
return &User{
ID: entity.NewID(),
Name: name,
Email: email,
Password: string(hash),
}, nil
}
更多信息:
user_domain
user_db
user_handler
根据文档,我认为我正确使用了CompareHashAndPassword
,但是我收到了这个错误。
英文:
I'm making a route to authenticate the user, when I create the user, I save the password as a hash and in the authentication I created this function to validate the password using the crypto/bcrypt lib:
func (user *User) ValidatePassword(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
if err != nil {
println(user.Password, password)
panic(err)
}
return err == nil
}
when saving the user everything works fine, but when I authenticate, the password validation returns this error:
// hashes compared
$2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa
// error
http: panic serving 127.0.0.1:62939: crypto/bcrypt: hashedPassword is not the hash of the given password
goroutine 20 [running]:
net/http.(*conn).serve.func1()
I create a hash and convert to string to save:
func NewUser(name, email, password string) (*User, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
return &User{
ID: entity.NewID(),
Name: name,
Email: email,
Password: string(hash),
}, nil
}
More info:
user_domain
user_db
user_handler
According to the documentation, I think I'm using CompareHashAndPassword
correctly, but I get this error
答案1
得分: 2
> // hashes compared
> $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa
这里的日志意味着一个哈希密码被传递给(*User).ValidatePassword
和bcrypt.CompareHashAndPassword
比较两个哈希密码。这是不正确的,bcrypt.CompareHashAndPassword
应该比较一个哈希密码和一个明文密码。
附注 这样做Password: string(hash)
是一个不好的主意。虽然这在语言规范中是允许的,但生成的字符串可能包含无效的Unicode代码点,其他软件可能无法接受它或正确处理它。例如,无效的代码点会被PostgreSQL拒绝。以下演示将抛出错误消息:ERROR: invalid byte sequence for encoding "UTF8": 0xff (SQLSTATE 22021)
。我认为你可以将Password
的数据类型更改为[]byte
,并将哈希值以二进制数据的形式存储在数据库中。
package main
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v5"
)
func main() {
urlExample := "postgres://postgres:sa123@localhost:5432/taop"
conn, err := pgx.Connect(context.Background(), urlExample)
if err != nil {
fmt.Fprintf(os.Stderr, "无法连接到数据库:%v\n", err)
os.Exit(1)
}
defer conn.Close(context.Background())
_, err = conn.Exec(context.Background(), "CREATE TABLE students(password TEXT)")
if err != nil {
panic(err)
}
_, err = conn.Exec(context.Background(), "INSERT INTO students(name) VALUES ($1)", string([]byte{0xff, 0xfe, 0xfd}))
if err != nil {
panic(err)
}
}
英文:
> // hashes compared
> $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa
The logs here means that a hashed password is passed to (*User).ValidatePassword
and bcrypt.CompareHashAndPassword
compares two hashed passwords. This is incorrect, bcrypt.CompareHashAndPassword
is supposed to compare a hashed password and a plain password.
P.S. It's a bad idea to do this Password: string(hash)
. This is allowed by the language spec, but the resulting string could contain invalid Unicode code points, and other software may not accept it or handle it correctly. For example, invalid code point is rejected by PostgreSQL. The following demo will panic with message: ERROR: invalid byte sequence for encoding "UTF8": 0xff (SQLSTATE 22021)
. I think you can change the data type of Password
to []byte
and store the hashed value as binary data in the database.
package main
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v5"
)
func main() {
urlExample := "postgres://postgres:sa123@localhost:5432/taop"
conn, err := pgx.Connect(context.Background(), urlExample)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer conn.Close(context.Background())
_, err = conn.Exec(context.Background(), "CREATE TABLE students(password TEXT)")
if err != nil {
panic(err)
}
_, err = conn.Exec(context.Background(), "INSERT INTO students(name) VALUES ($1)", string([]byte{0xff, 0xfe, 0xfd}))
if err != nil {
panic(err)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论