Golang如何在MySQL数据库中存储字节切片

Golang如何在MySQL数据库中存储字节切片 你好,我想在数据库中存储用户密码。我使用了’bcrypt’包进行加密,然后将其转换为字符串,但我觉得这种存储方式很糟糕。bcrypt的GenerateFromPassword方法返回的是字节切片,那么我应该如何在MySQL数据库中存储这个值呢?稍后我还需要在登录页面获取这个密码,与用户输入进行比较。

// 代码示例待补充
2 回复

我对MySQL不是特别熟悉(我个人99%的时间都在使用PostgreSQL),但如果你想要的话,可以存储字符串。只需将字节切片进行十六进制编码转换为字符串即可:

package main

import (
	"encoding/hex"
	"fmt"
)

func main() {
	data := []byte{123, 12, 13, 31}
	fmt.Println(hex.EncodeToString(data))
}

https://play.golang.org/p/0wc3SPnZD-A

更多关于Golang如何在MySQL数据库中存储字节切片的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在MySQL中存储bcrypt生成的字节切片,最合适的方式是将其转换为Base64编码的字符串存储。bcrypt生成的哈希值包含salt和哈希结果,直接存储为字符串是标准做法。

以下是完整的示例代码:

package main

import (
    "database/sql"
    "encoding/base64"
    "fmt"
    "log"

    "golang.org/x/crypto/bcrypt"
    _ "github.com/go-sql-driver/mysql"
)

// 用户注册时存储密码
func storePassword(db *sql.DB, username, plainPassword string) error {
    // 使用bcrypt生成密码哈希
    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(plainPassword), bcrypt.DefaultCost)
    if err != nil {
        return err
    }

    // 将字节切片转换为Base64字符串存储
    encodedPassword := base64.StdEncoding.EncodeToString(hashedPassword)

    // 存储到数据库
    _, err = db.Exec("INSERT INTO users (username, password) VALUES (?, ?)", username, encodedPassword)
    return err
}

// 用户登录时验证密码
func verifyPassword(db *sql.DB, username, plainPassword string) (bool, error) {
    var encodedPassword string
    err := db.QueryRow("SELECT password FROM users WHERE username = ?", username).Scan(&encodedPassword)
    if err != nil {
        return false, err
    }

    // 从Base64字符串解码回字节切片
    hashedPassword, err := base64.StdEncoding.DecodeString(encodedPassword)
    if err != nil {
        return false, err
    }

    // 使用bcrypt比较密码
    err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(plainPassword))
    if err != nil {
        if err == bcrypt.ErrMismatchedHashAndPassword {
            return false, nil
        }
        return false, err
    }

    return true, nil
}

// 创建用户表(如果需要)
func createTable(db *sql.DB) error {
    _, err := db.Exec(`
        CREATE TABLE IF NOT EXISTS users (
            id INT AUTO_INCREMENT PRIMARY KEY,
            username VARCHAR(255) UNIQUE NOT NULL,
            password TEXT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    `)
    return err
}

func main() {
    // 连接数据库
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database_name")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 创建表
    err = createTable(db)
    if err != nil {
        log.Fatal(err)
    }

    // 示例:存储用户密码
    err = storePassword(db, "john_doe", "mysecretpassword")
    if err != nil {
        log.Fatal(err)
    }

    // 示例:验证用户密码
    isValid, err := verifyPassword(db, "john_doe", "mysecretpassword")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Password verification result: %t\n", isValid)
}

数据库表结构建议:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) UNIQUE NOT NULL,
    password TEXT NOT NULL,  -- 存储Base64编码的bcrypt哈希
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

这种方式有几个优势:

  1. Base64编码确保所有字节都能安全存储在TEXT字段中
  2. 保持了bcrypt哈希的完整性
  3. 便于后续的密码验证操作
  4. 符合安全最佳实践

在MySQL中,建议使用TEXT类型字段来存储Base64编码后的字符串,因为bcrypt哈希的长度是固定的60字节,Base64编码后约为80-88个字符。

回到顶部