hashedSecret 太短,无法成为 bcrypted 密码而不是 auth

Lea*_*cim 3 postgresql go

我正在调整这篇博文中的登录功能。User 结构(见下文)有四个字段:id、name、email 和password。您可以看到下面数据库中的一行。登录功能fmt.Println中显示用户查询数据库后是这样的

 &{3 testuser $2a$10$hS7sth8jIBN2/IXFTWBibu3Ko5BXm9zHO5AJZRAbAOQ04uv.Gs5Ym [116 101 115 116 117 115 101 114 64 103 109 97 105 108 46 99 111 109]}
Run Code Online (Sandbox Code Playgroud)

换句话说,它有id(3)、name(testuser)、散列密码,但还有一个数字数组,这让我有点惊讶,因为它不在数据库的行中(见下文)。您还会注意到,fmt.Println即使在数据库的行中可见电子邮件,也不会显示电子邮件,因此这里似乎存在问题。

当 bcrypt 比较函数中的哈希值和密码时Login,它给了我这个错误

hashedSecret too short to be a bcrypted password not auth
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么会抛出这个错误吗?

func Login(password, email string) (u *User, err error) {
    u = &User{}
    err = db.QueryRow("select * from users where email=$1 ", email).Scan(&u.Id, &u.Name, &u.Password, &u.Email)
    fmt.Println("u", u)

    if err != nil {
        fmt.Println("err", err)
    }   

    err = bcrypt.CompareHashAndPassword(u.Password, []byte(password))
    if err != nil {
        u = nil
    }
    return
}
Run Code Online (Sandbox Code Playgroud)

我有一个包含以下字段的用户结构

type User struct {
    Id       int
    Name     string
    Email    string
    Password []byte
}
Run Code Online (Sandbox Code Playgroud)

我在 postgres 中为它创建了一个表,如下所示

CREATE TABLE "public"."users" (
    "id" int4 NOT NULL DEFAULT nextval('users_id_seq'::regclass),
    "username" varchar(255) NOT NULL COLLATE "default",
    "email" varchar(255) NOT NULL COLLATE "default",
    "password" bytea 
)
WITH (OIDS=FALSE);
Run Code Online (Sandbox Code Playgroud)

这是数据库中的一行

id |  username  |        email         |                                                          password                                                          
----+------------+----------------------+----------------------------------------------------------------------------------------------------------------------------
  3 | testuser   | testuser@gmail.com   | \x24326124313024685337737468386a49424e322f495846545742696275334b6f3542586d397a484f35414a5a524162414f51303475762e477335596d
Run Code Online (Sandbox Code Playgroud)

pet*_*rSO 6

数字数组是电子邮件地址。

package main

import (
    "fmt"
)

func main() {
    email := []byte{116, 101, 115, 116, 117, 115, 101, 114, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109}
    fmt.Println(email)
    fmt.Println(string(email))
}
Run Code Online (Sandbox Code Playgroud)

输出:

[116 101 115 116 117 115 101 114 64 103 109 97 105 108 46 99 111 109]
testuser@gmail.com
Run Code Online (Sandbox Code Playgroud)

经过进一步研究,我发现你有select *。不要那样做!您得到的是数据库返回的项目,但不一定是您想要的。始终明确您想要返回的字段及其顺序。

根据select *,使用CREATE TABLE定义,您可能会得到idusernameemailpassword。在您的 中Scan,您将 User类型设置IdidNameto usernamePasswordtoemailEmailto password。换句话说,u.Password包含email(它们具有相同的 Go 数据类型)并且email太短而无法伪装成哈希密码。

select匹配和 中的字段Scan,例如,

"select id, username, password, email from users where email=$1 "

Scan(&u.Id, &u.Name, &u.Password, &u.Email)
Run Code Online (Sandbox Code Playgroud)