golang 使用 bcrypt 实现密码加密 | 青训营笔记

您所在的位置:网站首页 Bcrypt加密 golang 使用 bcrypt 实现密码加密 | 青训营笔记

golang 使用 bcrypt 实现密码加密 | 青训营笔记

2023-03-13 22:37| 来源: 网络整理| 查看: 265

golang 使用 bcrypt 实现密码加密

这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记

01 简介

在完成许多的项目当中,注册和登录这两个功能几乎是必不可少的。

将用户的密码加密后再存入数据库的操作是必要的。我们通常对密码进行加密,然后存放在数据库中,在用户进行登录的时候,将其输入的密码与数据库中存放的密文进行比较,以验证用户密码是否正确。目前,MD5和Bcrypt比较流行。

BCrypt加密: 一种加盐的单向Hash,不可逆的加密算法,同一种明文(plaintext),每次加密后的密文都不一样,而且不可反向破解生成明文,破解难度很大。 MD5加密: 是不加盐的单向Hash,不可逆的加密算法,同一个密码经过hash的时候生成的是同一个hash值,在大多数的情况下,有些经过md5加密的方法将会被破解。

Bcrypt生成的密文是60位的。而MD5的是32位的。相对来说,Bcrypt比MD5更安全,但加密更慢。

02 实现

其中使用的数据库、框架:

mysql gorm gin bcrypt

主要分三步:

1、go get 一下这个算法的包

 go get golang.org/x/crypto/bcrypt 复制代码

2、生成、比对

实现GetPwd() 函数给密码加密、ComparePwd() 函数比对密码。

func GetPwd(pwd string) ([]byte, error) func ComparePwd(pwd1 string, pwd2 string) bool

主要使用了这两个函数: bcrypt.GenerateFromPassword() 和 bcrypt.CompareHashAndPassword()

注意:分清 pwd1 、 pwd2分别代表什么,pwd1 是数据库的已经加密的密码, pwd2 是用户实际的密码。

3、在 controller/user.go 实现登录、注册逻辑

在这次实现极简版抖音为例,主要有以下代码实现:

controller/user.go  package controller  ​  import (   "douyin/dao"   "douyin/model"   "fmt"   "github.com/dgrijalva/jwt-go"   "github.com/gin-gonic/gin"   "golang.org/x/crypto/bcrypt"   "log"   "net/http"  )  ​  type UserLoginResponse struct {   model.Response   UserId int64  `json:"user_id,omitempty"`   Token  string `json:"token"`  }  ​  type UserResponse struct {   model.Response   User model.Userinfo `json:"user"`  }  ​  func Register(c *gin.Context) {   username := c.Query("username")   password := c.Query("password")  ​   token, _ := GenToken(username, password)  ​   // 查找用户是否存在   user, err := dao.Mgr.IsExist(username)   if err != nil {   log.Println(err)   }  ​   if user.Name != "" {   fmt.Println("已存在!")   c.JSON(http.StatusOK, UserLoginResponse{   Response: model.Response{StatusCode: 1, StatusMsg: "User already exist"},   })   return   }  ​   // encrypted : 已加密的密码   encrypted, _ := GetPwd(password)   userinfo := model.Userinfo{   Name:     username,   Password: string(encrypted),   }   // 将加密的密码写入数据库   err = dao.Mgr.Register(userinfo)   if err != nil {   log.Println(err)   }  ​   c.JSON(http.StatusOK, UserLoginResponse{   Response: model.Response{StatusCode: 0},   UserId:   userinfo.Id,   Token:    token,   })  }  ​  func Login(c *gin.Context) {   username := c.Query("username")   password := c.Query("password")  ​   token, _ := GenToken(username, password)  ​   // 查找用户是否存在   user, err := dao.Mgr.IsExist(username)   if err != nil {   log.Println(err)   }  ​   if user.Name == "" {   fmt.Println("用户不存在!")   c.JSON(http.StatusOK, UserLoginResponse{   Response: model.Response{StatusCode: 1, StatusMsg: "User doesn't exist"},   })   return   }  ​   if ComparePwd(user.Password, password) {   fmt.Println("登陆成功!")   c.JSON(http.StatusOK, UserLoginResponse{   Response: model.Response{StatusCode: 0},   UserId:   user.Id,   Token:    token,   })   } else {   c.JSON(http.StatusOK, UserLoginResponse{   Response: model.Response{StatusCode: 1, StatusMsg: "Password is not correct"},   })   }  }  ​  // GetPwd 给密码加密  func GetPwd(pwd string) ([]byte, error) {   hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)   return hash, err  }  ​  // ComparePwd 比对密码  func ComparePwd(pwd1 string, pwd2 string) bool {   // Returns true on success, pwd1 is for the database.   err := bcrypt.CompareHashAndPassword([]byte(pwd1), []byte(pwd2))   if err != nil {   return false   } else {   return true   }  } 复制代码 dao/db_init.go

该文件的功能是:做数据库连接、操作数据库函数的声明。

 package dao  ​  import (   "douyin/model"   "douyin/pkg/constrant"   "gorm.io/driver/mysql"   "gorm.io/gorm"   "gorm.io/gorm/schema"   "log"  )  ​  type manager struct {   db *gorm.DB  }  ​  type Manager interface {   // Register 注册   Register(user model.Userinfo) error   // IsExist 判断是否用户是否已存在   IsExist(username string) (model.Userinfo, error)  }  ​  var Mgr Manager  ​  func init() {   db, err := gorm.Open(mysql.Open(root:xxxxxx@tcp(xxx.xx.xxx.xxx)/douyin?&parseTime=True&loc=Local), &gorm.Config{   NamingStrategy: schema.NamingStrategy{   TablePrefix:   "t_",   SingularTable: true,   },   })   if err != nil {   log.Fatal("Failed to init db:", err)   }   Mgr = &manager{db: db}  ​  } 复制代码 dao/user.go

实际操作数据库的函数:

 package dao  ​  import (   "douyin/model"  )  ​  func (mgr manager) Register(userinfo model.Userinfo) error {   result := mgr.db.Create(&userinfo)   return result.Error  }  ​  func (mgr manager) IsExist(username string) (model.Userinfo, error) {   var userinfo model.Userinfo   result := mgr.db.Model(&model.Userinfo{}).Where("name=?", username).Find(&userinfo)  ​   return userinfo, result.Error  } 复制代码 03 总结

目前,MD5 和 Bcrypt 比较流行。相对来说,Bcrypt 比 MD5 更安全,但加密更慢。

实现 bcrypt 加密分三个步骤:

1、go get 一下这个算法的包

 go get golang.org/x/crypto/bcrypt 复制代码

2、生成、比对

实现GetPwd() 函数给密码加密、ComparePwd() 函数比对密码。

func GetPwd(pwd string) ([]byte, error) func ComparePwd(pwd1 string, pwd2 string) bool

3、在 controller 实现登录、注册逻辑



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3