【问题标题】:hashedSecret too short to be a bcrypted password not authhashedSecret 太短,不能成为 bcrypted 密码而不是 auth
【发布时间】:2014-08-16 21:22:32
【问题描述】:

我正在调整this blogpost 的登录功能。 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]}

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

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

hashedSecret too short to be a bcrypted password not auth

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

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
}

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

type User struct {
    Id       int
    Name     string
    Email    string
    Password []byte
}

我像这样在 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);

这是数据库中的一行

id |  username  |        email         |                                                          password                                                          
----+------------+----------------------+----------------------------------------------------------------------------------------------------------------------------
  3 | testuser   | testuser@gmail.com   | \x24326124313024685337737468386a49424e322f495846545742696275334b6f3542586d397a484f35414a5a524162414f51303475762e477335596d

【问题讨论】:

    标签: postgresql go


    【解决方案1】:

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

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

    输出:

    [116 101 115 116 117 115 101 114 64 103 109 97 105 108 46 99 111 109]
    testuser@gmail.com
    

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

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

    匹配selectScan中的字段,例如,

    "select id, username, password, email from users where email=$1 "
    
    Scan(&u.Id, &u.Name, &u.Password, &u.Email)
    

    【讨论】:

    • 谢谢。如果可以的话,请稍微解释一下(我将非常感激,您的回答只是部分回答了这个问题:))这是否意味着电子邮件以某种方式插入到密码列中(类型为 []byte /bytea )?为什么电子邮件是这样的?如您所见,它应该在数据库中输入text?这是否解释了为什么抛出问题标题中的错误hashedSecret too short to be a bcrypted password not auth
    • 非常感谢,所以您在答案的倒数第二段中所说的是 Scan 将指针分配给它碰巧与数字对齐的任何列。 email 在 Create Table 定义中排名第三,因此传递给 scan 的第三个参数(密码)被分配给电子邮件。
    • 正确 - 它们被解组的顺序很重要。查询只返回行,而 Scan 只是按照提供的顺序将它们一个一个地放入您的结构字段中,前提是类型兼容。
    • 是的,您可以从fmt.Println("u", u) 语句的输出中看到这一点。它按照 Go User 类型(IdNameEmailPassword)的顺序打印 struct 字段,但 u.Emailu.Password 字段的值是相反的.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 2018-03-24
    • 2016-11-02
    • 2014-01-15
    • 1970-01-01
    • 2022-09-23
    相关资源
    最近更新 更多