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

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

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

  • 方案1:bcrypt
  • 方案2:scrypt(参考资料中的专家方案)

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

image.png

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

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

运行结果:

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

gorm 钩子介绍使用

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


image.png

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

image.png

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

model/User.go

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
}
//......


相关文章
|
3月前
|
druid Java 数据库
druid+springboot加解密Druid链接池配置加密密码链接数据库
druid+springboot加解密Druid链接池配置加密密码链接数据库
223 0
|
2月前
|
Go 数据安全/隐私保护
go 基于gin编写encode、decode、base64加密接口
go 基于gin编写encode、decode、base64加密接口
18 2
|
3月前
|
算法 数据库 数据安全/隐私保护
rsa加密解密,使用rsa对密码加密
rsa加密解密,使用rsa对密码加密
|
17天前
|
安全 数据安全/隐私保护 Python
|
4天前
|
安全 Nacos 数据安全/隐私保护
【技术干货】破解Nacos安全隐患:连接用户名与密码明文传输!掌握HTTPS、JWT与OAuth2.0加密秘籍,打造坚不可摧的微服务注册与配置中心!从原理到实践,全方位解析如何构建安全防护体系,让您从此告别数据泄露风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其连接用户名和密码的明文传输成为安全隐患。本文探讨加密策略提升安全性。首先介绍明文传输风险,随后对比三种加密方案:HTTPS简化数据保护;JWT令牌减少凭证传输,适配分布式环境;OAuth2.0增强安全,支持多授权模式。每种方案各有千秋,开发者需根据具体需求选择最佳实践,确保服务安全稳定运行。
17 0
|
2月前
|
安全 网络协议 网络安全
【红队APT】反朔源&流量加密&CS&MSF&证书指纹&C2项目&CDN域前置
【红队APT】反朔源&流量加密&CS&MSF&证书指纹&C2项目&CDN域前置
|
2月前
|
算法 JavaScript 安全
一篇文章讲明白JavaScript_提交表单和MD5算法密码加密
一篇文章讲明白JavaScript_提交表单和MD5算法密码加密
18 0
|
2月前
|
算法 JavaScript 安全
一篇文章讲明白JavaScript_提交表单和MD5算法密码加密
一篇文章讲明白JavaScript_提交表单和MD5算法密码加密
21 0
|
2月前
|
存储 Java Apache
杨校老师课堂之用户登录时如何进行密码加密存储到数据库
杨校老师课堂之用户登录时如何进行密码加密存储到数据库
22 0