无论是什么样的系统,只要有用户,那么用户安全就是不可避免的问题,这节我们会讲解一下Md5和密码加密的方式。
Md5序列化方法
在utils文件夹中新增md5.go文件,用来存放md5相关配置, 添加以下文件:
package utils
import (
"crypto/md5"
"encoding/hex"
"strings"
)
// Md5Encode 小写
func Md5Encode(data string) string {
h := md5.New()
h.Write([]byte(data))
tempStr := h.Sum(nil)
return hex.EncodeToString(tempStr)
}
// MD5Encode 大写
func MD5Encode(data string) string {
return strings.ToUpper(Md5Encode(data))
}
密码加密与解密
密码学是一种很复杂的学科,细致起来非常的讲究,所以这里用最简单的方法加密:通过md5序列化和添加随机数。
添加加密解密方法
// MakePassword 加密
func MakePassword(plainpwd, salt string) string {
return Md5Encode(plainpwd + salt)
}
// ValidPassword 解密
func ValidPassword(plainpwd, salt string, password string) bool {
return Md5Encode(plainpwd+salt) == password
}
为user结构体中新增随机数字段:Salt
type UserBasic struct {
gorm.Model
Name string `gorm:"column:name" json:"name"`
Password string `gorm:"column:password" json:"password"`
Phone string `valid:"matches(^1[3-9]{1}\d{9}$)" gorm:"column:phone" json:"phone"`
Email string `valid:"email" gorm:"column:email" json:"email"`
Identity string `gorm:"column:identity" json:"identity"`
ClientIp string `gorm:"column:client_ip" json:"client_ip"`
ClientPort string `gorm:"column:client_port" json:"client_port"`
Salt string `gorm:"column:salt" json:"salt"`
LoginTime uint64 `gorm:"column:login_time" json:"login_time"`
HeartbeatTime uint64 `gorm:"column:heartbeat_time" json:"heartbeat_time"`
LoginOutTime uint64 `gorm:"column:login_out_time" json:"login_out_time"`
IsLogout bool `gorm:"column:is_logout" json:"is_logout"`
DeviceInfo string `gorm:"column:device_info" json:"device_info"`
}
将加密方法应用到service中的CreateUser方法中
- 生成随机数并将随机数保存到结构体中
- 将随机数拼上密码保存起来
// CreateUser
// @Summary 新增用户
// @Tags 用户模块
// @param name query string false "用户名"
// @param password query string false "密码"
// @param rePassword query string false "确认密码"
// @Success 200 {string} json{"code", "message"}
// @Router /user/createUser [get]
func CreateUser(c *gin.Context) {
user := models.UserBasic{}
user.Name = c.Query("name")
password := c.Query("password")
rePassword := c.Query("rePassword")
salt := fmt.Sprintf("%06d", rand.Int31())
user.Salt = salt
data := models.FindUserByName(user.Name)
if data.Name != "" {
c.JSON(-1, gin.H{
"message": "用户名已经注册",
})
return
}
if password != rePassword {
c.JSON(-1, gin.H{
"message": "两次密码不一致",
})
return
}
user.Password = utils.MakePassword(password, salt)
models.CreateUser(&user)
c.JSON(200, gin.H{
"message": "新增用户成功",
})
}
生成新的表单
由于我们为结构体添加了新的字段,所以我们需要重新生成表,运行之前生成表的test方法:
package main
import (
"ginchat/models"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
db, err := gorm.Open(mysql.Open("用户名:密码@数据库地址/ginchat?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 迁移 schema
db.AutoMigrate(&models.UserBasic{})
}
运行main.go文件,新增一个用户:如果出现以下表单,代表已经成功: