前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >gin博客项目复盘--04用户密码加密

gin博客项目复盘--04用户密码加密

作者头像
微客鸟窝
发布2022-11-07 14:49:42
8760
发布2022-11-07 14:49:42
举报
文章被收录于专栏:Go语言指北Go语言指北

用户密码加密

参考资料:https://astaxie.gitbooks.io/build-web-application-with-golang/content/zh/09.5.html

  • 方案1:bcrypt
    • https://pkg.go.dev/golang.org/x/crypto/bcrypt
  • 方案2:scrypt(参考资料中的专家方案)
    • https://pkg.go.dev/golang.org/x/crypto/scrypt

本文采用方案1进行明文密码的加密操作,Bcrypt是单向Hash加密算法,此算法对于同一个明文密码,每次生成的hash不一样,每次加密,都会采用不同的盐值来进行加密,最后返回的 hash 值包含盐值等信息的密文。

其中:$是分割符,无意义;2a是bcrypt加密版本号;10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

  • 安装 crypto/bcrypt
    • go get -u golang.org/x/crypto/bcrypt
  1. 生成hash值
代码语言:javascript
复制
bcrypt.GenerateFromPassword([]byte(password), 10)
  • 10 为 cost 默认值,加密级别系数,越大越安全但性能开下也随之增大
  1. 密码验证
代码语言:javascript
复制
bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) 
  • 参数1 为保存在数据库中的密码hash(之前加密后的密码)
  • 参数2 为前端传过来要验证的密码
  • 返回值 返回true说明密码验证通过
  1. 完整示例
代码语言:javascript
复制
package main

import (
 "fmt"
 "golang.org/x/crypto/bcrypt"
)

func HashPassword(password string) (string, error) {
 bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10)
 return string(bytes), err
}
func CheckPasswordHash(hash, password string) bool {
 err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
 return err == nil
}

func main() {
 password := "123456"
 hash, _ := HashPassword(password)

 fmt.Println("Password:", password)
 fmt.Println("Hash:    ", hash)

 match := CheckPasswordHash(hash, password)
 fmt.Println("Match:   ", match)
}

运行结果:

代码语言:javascript
复制
Password: 123456
Hash:     $2a$10$O.do8guW0m5PAphJuuMH7eVSTRuZAtVNsrLLORH6pMzFWdqCmc2Wu
Match:    true

gorm 钩子介绍使用

参考资料 gorm.io/zh_CN/docs/hooks.html

使用钩子来实现密码加密后存库,我们之前使用的方式 data.Password = BcryptPW(data.Password),替换成钩子后,框架会在写入库前,自动调用钩子函数,来将密码进行加密处理:

加密及钩子在项目中的使用

model/User.go

代码语言:javascript
复制
package model

import (
 "ginVue3blog/utils/errmsg"
 "golang.org/x/crypto/bcrypt"
 "gorm.io/gorm"
 "log"
)

type User struct {
 gorm.Model
 Username string `gorm:"type:varchar(20);not null " json:"username" validate:"required,min=4,max=12" label:"用户名"`
 Password string `gorm:"type:varchar(500);not null" json:"password" validate:"required,min=6,max=120" label:"密码"`
 Role     int    `gorm:"type:int;DEFAULT:2" json:"role" validate:"required,gte=2" label:"角色码"`
}
//......
// CreateUser 新增用户
func CreateUser(data *User) int {
 //data.Password = BcryptPW(data.Password)
 err := db.Create(&data).Error
 if err != nil {
  return errmsg.ERROR //500
 }
 return errmsg.SUCCSE
}
// ChangePassword 修改密码
func ChangePassword(id int, data *User) int {
 //var user User
 //var maps = make(map[string]interface{})
 //maps["password"] = data.Password

 err = db.Select("password").Where("id=?", id).Updates(&data).Error
 if err != nil {
  return errmsg.ERROR
 }
 return errmsg.SUCCSE
}
//使用钩子 BeforeCreate 密码加密&权限控制
func (u *User) BeforeCreate(_ *gorm.DB) (err error) {
 u.Password = BcryptPW(u.Password)
 u.Role = 2
 return nil
}

func (u *User) BeforeUpdate(_ *gorm.DB) (err error) {
 u.Password = BcryptPW(u.Password)
 return nil
}

// BcryptPW 生成密码
func BcryptPW(password string) string {
 const cost = 10 //加密级别系数,越大越安全但性能开下也随之增大

 HashPw, err := bcrypt.GenerateFromPassword([]byte(password), cost)
 if err != nil {
  log.Fatal(err)
 }
 return string(HashPw)
}
// CheckLoginFront 前台登录
func CheckLoginFront(username, password string) (User, int) {
 var user User
 var PasswordErr error

 db.Where("username=?", username).First(&user)
 PasswordErr = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))

 if user.ID == 0 {
  return user, errmsg.ERROR_USER_NOT_EXIST
 }
 if PasswordErr != nil {
  return user, errmsg.ERROR_PASSWORD_WRONG
 }
 return user, errmsg.SUCCSE
}
//......

下一节,JWT 的使用,敬请期待...

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微客鸟窝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用户密码加密
    • gorm 钩子介绍使用
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档