一般前端把用户密码发给服务端,服务端实际业务中如何存储密码呢,如何存储密码才能保证密码不被开发者获取或者被截取呢,保证密码的安全
加盐的加密方式现在的企业开发大都采用这种方式了,比较安全的密码存储算法要求盐值至少在 8 Bytes 以上
首先肯定不可能明文传输,必须对密码加密,那怎么加密呢,我往下细看。一般加密比如 md5 直接为什么不行,因为破解者可能通过暴力破解的方式,字典破解的方式还是能找到原始密码是啥
因此我需要一种加盐的加密方式:比如 md5 加盐加密,即盐是一个随机生成的字符串,然后我们将 salt 和原始密码连接起来,将其加密,这样就不容易被破解了。即先加盐再加密
md5 加盐方式
注册时候:
- 用户密码和其他信息到服务端
- 服务端识别密码,随机函数生成盐和密码做拼接
- 拼接后进行 md5 加密
- 将 salt 和 hash 值存放数据库
登录:
- 用户密码到服务端
- 服务端获取 salt,对密码进行加盐加密和数据库比对
- 比对正确登录 ok,比对错误则失败
bcrypt 方式
特点:相比于 md5,bcrypt 每次相同密码生成的密文都不同,md5 则相同,bcrypt 加密计算比 md5 更久,因此破解更难
import "golang.org/x/crypto/bcrypt"// EncryptPassword 将密码加密,需要传入密码返回的是加密后的密码
func EncryptPassword(password string) (string, error) {// 加密密码,使用 bcrypt 包当中的 GenerateFromPassword 方法,bcrypt.DefaultCost 代表使用默认加密成本encryptPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)if err != nil {// 如果有错误则返回异常,加密后的空字符串返回为空字符串,因为加密失败return "", err} else {// 返回加密后的密码和空异常return string(encryptPassword), nil}
}// EqualsPassword 对比密码是否正确
func EqualsPassword(password, encryptPassword string) bool {// 使用 bcrypt 当中的 CompareHashAndPassword 对比密码是否正确,第一个参数为加密后的密码,第二个参数为未加密的密码err := bcrypt.CompareHashAndPassword([]byte(encryptPassword), []byte(password))// 对比密码是否正确会返回一个异常,按照官方的说法是只要异常是 nil 就证明密码正确return err == nil
}