golang 使用 bcrypt 实现密码加密 | 青训营笔记 |
您所在的位置:网站首页 › Bcrypt加密 › golang 使用 bcrypt 实现密码加密 | 青训营笔记 |
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) bool3、在 controller 实现登录、注册逻辑 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |