Golang加密字符串并存储到SQLite数据库
这是一段 Golang 代码,它实现了以下功能:
从标准输入读取用户名和密码;将密码进行 bcrypt 加密,并将用户名和加密后的密码存储到 SQLite 数据库中;查询数据库,获取指定用户名的记录,并将其输出到日志中。
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
"golang.org/x/crypto/bcrypt"
)
//定义了一个名为 `Users` 的结构体类型,包含用户名和密码两个字段。
type Users struct {
Username string
Password []byte
}
//定义了一个名为 `encrypt_str` 的函数,接受用户名和密码两个字符串作为输入参数,将密码使用 bcrypt 加密,并将用户名和加密后的密码封装到一个 `Users` 结构体中返回。
func encrypt_str(username, password string) (*Users, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
user := &Users{
Username: username,
Password: hashedPassword,
}
return user, nil
}
//定义了一个名为 `checkPassword` 的函数,接受一个 `Users` 结构体和一个密码字符串作为输入参数,使用 bcrypt 比较输入的密码和结构体中保存的密码是否匹配,并返回比较结果。
func checkPassword(user *Users, password string) bool {
err := bcrypt.CompareHashAndPassword(user.Password, []byte(password))
return err == nil
}
//定义了一个名为 `readInput` 的函数,从标准输入中读取用户名和密码,并返回两个字符串。
func readInput() (name string, p string) {
// 读取标准输入
var username, pwd string
fmt.Printf("请输入用户名: ")
// fmt.Println("请输入一行文字: ")
fmt.Scanln(&username)
fmt.Printf("请输入密码: ")
fmt.Scanln(&pwd)
return username, pwd
}
//定义了一个名为 `QueryUser` 的函数,接受一个 `sql.DB` 类型的数据库连接对象和一个字符串类型的用户名作为输入参数,查询数据库中是否存在指定的用户名,并返回查询结果的bool值。
func QueryUser(db *sql.DB, username string) bool {
s, err3 := db.Prepare("select * from users where username = ?")
if err3 != nil {
log.Fatal(err3)
}
var id int
var n string
var pwd string
defer s.Close()
err := s.QueryRow(username).Scan(&id, &n, &pwd)
if err == sql.ErrNoRows {
return true
}
return false
}
func main() {
// 打开了一个名为users.db的SQLite数据库,并创建了一个名为users的数据表
db, err := sql.Open("sqlite3", "./users.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 创建users数据表
_, err = db.Exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT unique, password TEXT)")
if err != nil {
log.Fatal(err)
}
//调用readInput函数读取用户输入,并使用encrypt_str函数加密密码
name, p := readInput()
// fmt.Scanln(&input)
// fmt.Printf("username: %st password: %sn", username, pwd)
u, err2 := encrypt_str(name, p)
if err2 != nil {
log.Fatal(err2)
}
// fmt.Printf("u: %vn", u)
// 调用QueryUser函数查询数据库中是否已经存在该用户,如果不存在,将用户名和加密后的密码插入到数据库中
b := QueryUser(db, u.Username)
if b {
// 将数据存储到数据库中
stmt, err := db.Prepare("INSERT INTO users(username, password) VALUES(?, ?)")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
_, err = stmt.Exec(u.Username, u.Password)
if err != nil {
log.Fatal(err)
}
fmt.Println("数据已成功存储到数据库中")
}
// 查询数据表
rows, err := db.Query("SELECT * FROM users where username = ?", u.Username)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id int64
username string
password string
)
if err := rows.Scan(&id, &username, &password); err != nil {
log.Fatal(err)
}
log.Printf("id: %d tname: %s tpassword: %sn", id, username, password)
}
// fmt.Printf("%v", rows)
}
以下是对该代码的详细说明:
这段代码主要做的是用户输入用户名和密码,程序会对密码进行加密sql字符串包含某个字符串,然后将用户名和加密后的密码存储到 SQLite 数据库中。如果输入的用户名已经存在于数据库中,则不会再次存储到数据库中。程序还支持查询数据库中已有的用户信息。
以下是对代码的详细分析:
导入需要的包
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
"golang.org/x/crypto/bcrypt"
)
程序需要使用 database/sql 包来操作 SQLite 数据库,还需要使用 github.com/mattn/go-sqlite3 包来连接 SQLite 数据库。同时,还需要使用 golang.org/x/crypto/bcrypt 包来对用户密码进行加密。
定义 Users 结构体
type Users struct {
Username string
Password []byte
}
定义了一个名为 Users 的结构体,用来存储用户的用户名和密码。密码是一个字节数组,因为加密后的密码是无法直接显示的字符串。
实现密码加密和密码验证的函数
func encrypt_str(username, password string) (*Users, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
user := &Users{
Username: username,
Password: hashedPassword,
}
return user, nil
}
func checkPassword(user *Users, password string) bool {
err := bcrypt.CompareHashAndPassword(user.Password, []byte(password))
return err == nil
}
encrypt_str 函数用来将用户密码加密,函数接收用户名和明文密码作为参数,返回一个指向 Users 结构体的指针和一个可能发生的错误。加密的过程中,使用 bcrypt.GenerateFromPassword 函数生成一个哈希值,并将用户名和哈希值存储到 Users 结构体中。
checkPassword 函数用来验证用户密码是否正确。函数接收一个 Users 结构体指针和明文密码作为参数,如果明文密码和 Users 结构体中的哈希值匹配,则返回 true;否则返回 false。
定义读取用户输入的函数
func readInput() (name string, p string) {
var username, pwd string
fmt.Printf("请输入用户名: ")
fmt.Scanln(&username)
fmt.Printf("请输入密码: ")
fmt.Scanln(&pwd)
return username, pwd
}
readInput 函数用来读取用户输入的用户名和密码,并返回这两个值。
定义查询用户的函数
func QueryUser(db *sql.DB, username string) bool {
s, err3 := db.Prepare("select * from users where username = ?")
if err3 != nil {
log.Fatal(err3)
}
var id int
var n string
var pwd string
defer s.Close()
err := s.QueryRow(username).Scan(&id, &n, &pwd)
if err == sql.ErrNoRows {
return true
}
return false
}
在main函数中,首先创建了一个sqlite3数据库,如果数据库创建失败,会直接调用log.Fatal函数将错误打印并退出程序。然后,程序调用了readInput函数,获取用户输入的用户名和密码,并调用encrypt_str函数对密码进行加密。接下来,程序调用了QueryUser函数,查询数据库中是否已经存在该用户。如果存在,则不需要将该用户数据再次存储到数据库中;如果不存在,则程序将该用户数据存储到数据库中。
最后,查询数据表,将用户的数据打印出来。
在encrypt_str函数中,程序使用bcrypt对密码进行加密,生成的哈希值被存储在一个Users类型的结构体中。在checkPassword函数中,程序使用bcrypt.CompareHashAndPassword函数来检查密码是否正确。在readInput函数中,程序使用fmt.Scanln函数读取标准输入。
在QueryUser函数中,程序通过查询username字段来判断数据库中是否存在该用户,如果不存在sql字符串包含某个字符串,则返回true;否则返回false。在main函数中,程序首先调用QueryUser函数查询数据库中是否存在该用户,然后根据查询结果决定是否将该用户数据存储到数据库中。最后,程序使用db.Query函数查询数据表,并将查询结果打印出来。
———END———
限 时 特 惠:本站每日持续更新海量各大内部创业教程,一年会员只需128元,全站资源免费下载点击查看详情
站 长 微 信:jiumai99