从4开始,在后端系统中增加用户注册和登录功能

网友投稿 622 2022-09-07

从4开始,在后端系统中增加用户注册和登录功能

从4开始,在后端系统中增加用户注册和登录功能

本次我们接着上四篇文章进行讲解​​《从0开始,用Go语言搭建一个简单的后端业务系统》​​​、​​《从1开始,扩展Go语言后端业务系统的RPC功能》​​​、​​《从2开始,在Go语言后端业务系统中引入缓存》​​​以及​​《从3开始,在业务系统中增加分页功能》​​,这次是系统中比较核心的功能——用户登录&注册,这个功能其实本应该是最先实现的,但是由于不同因素的影响,放到了本次进行实现,不过也无伤大雅,后期我们都会不断的进行查漏补缺和优化来使我们的项目总体上更加优雅,话不多说,我们开始正文:

1 用户注册&登录流程

(1)注册流程

(2)登录流程

2 代码实现

user结构:

package modelimport ( "encoding/json")type User struct { Id int64 `json:"id"` Name string `json:"name"` LoginName string `json:"login_name"` Role int64 `json:"role"` Pwd string `json:"pwd"` CreateTime string `json:"create_time"`}func (user User) TableName() string { return "user_info"}func (user User) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "id": user.Id, "name": user.Name, "login_name": user.LoginName, "role": user.Role, "pwd": user.Pwd, "create_time": user.CreateTime, })}//Redis类似序列化操作func (user User) MarshalBinary() ([]byte, error) { return json.Marshal(user)}func (user User) UnmarshalBinary(data []byte) error { return json.Unmarshal(data, &user)}

dao层代码:

package daoimport ( "context" "count_num/pkg/model")type UserDao interface { // 添加一个 CreateUser(ctx context.Context, user model.User) bool // 根据ID查找一个 GetUserByUid(ctx context.Context, uId int64) model.User // 查找全部 GetAll(ctx context.Context, page int, limit int) []model.User // 根据ID修改一个 UpdateUserById(ctx context.Context, user model.User) bool // 根据登录名查找一个 GetUserByLoginName(ctx context.Context, loginName string) model.User}

dao层实现:

package implimport ( "context" "count_num/pkg/cache" "count_num/pkg/config" "count_num/pkg/model" "count_num/pkg/utils" "gorm.io/gorm")type UserDaoImpl struct { db *gorm.DB cache *cache.CountNumCacheDAOImpl}func NewUserDaoImpl() *UserDaoImpl { return &UserDaoImpl{db: config.DB, cache: cache.NewCountNumCacheDAOImpl()}}func (impl *UserDaoImpl) CreateUser(ctx context.Context, user model.User) bool { var u model.User impl.db.First(&u, "login_name", user.LoginName) if u.LoginName == user.LoginName { return false } user.Pwd = utils.GetMd5Str(user.Pwd) user.CreateTime = utils.NowTimeStr() impl.db.Save(&user) return true}func (impl *UserDaoImpl) GetUserByUid(ctx context.Context, uId int64) model.User { var user model.User impl.db.First(&user, "id", uId) return user}func (impl *UserDaoImpl) GetAll(ctx context.Context, page int, limit int) []model.User { users := make([]model.User, 0) if page <= 0 || limit <= 0 { impl.db.Find(&users) } else { impl.db.Limit(limit).Offset((page - 1) * limit).Find(&users) } return users}func (impl *UserDaoImpl) UpdateUserById(ctx context.Context, user model.User) bool { impl.db.Model(&model.User{}).Where("id = ?", user.Id).Updates(user) return true}func (impl *UserDaoImpl) GetUserByLoginName(ctx context.Context, loginName string) model.User { var user model.User impl.db.First(&user, "login_name", loginName) return user}

工具方法,用于生成token和MD5加密:

package utilsimport ( "bytes" "crypto/md5" "encoding/gob" "encoding/hex" "math/rand" "strings" "time")func GetMd5Str(str string) string { md5 := md5.New() var buf bytes.Buffer gob.NewEncoder(&buf).Encode(str) md5.Write(buf.Bytes()) return hex.EncodeToString(md5.Sum(nil))}func GetTokenStr() string { char := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" charArr := strings.Split(char, "") c := len(charArr) ran := rand.New(rand.NewSource(time.Now().Unix())) var str string = "" for i := 1; i <= 18; i++ { str = str + charArr[ran.Intn(c)] } return str}

工具方法:

package utilsimport ( "time")// NowTimeStr return 2022-01-21 12:21:31func NowTimeStr() string { return time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")}// NowTimeStamp return 1657255820func NowTimeStamp() int64 { return time.Now().Unix()}// TimeStamp2NowTimeStr 1657255820 -> 2022-01-21 12:21:31func TimeStamp2NowTimeStr(stamp int64) string { format := time.Unix(stamp, 0).Format("2006-01-02 15:04:05") return format}// NowTimeStr2TimeStamp 2022-01-21 12:21:31 -> 1657255820func NowTimeStr2TimeStamp(str string) int64 { var LOC, _ = time.LoadLocation("Asia/Shanghai") tim, _ := time.ParseInLocation("2006-01-02 15:04:05", str, LOC) return tim.Unix()}

controller层:

package controllerimport ( "count_num/pkg/dao/impl" "count_num/pkg/model" "count_num/pkg/utils" "count_num/pkg/web/auth" "encoding/json" "github.com/gin-gonic/gin" "io/ioutil")type UserControllerImpl struct { dao *impl.UserDaoImpl}type UserController interface { CreateUser(c *gin.Context) FindUserByLoginNameAndPwd(c *gin.Context) Register(c *gin.Context)}func NewUserController() *UserControllerImpl { return &UserControllerImpl{dao: impl.NewUserDaoImpl()}}func (impl UserControllerImpl) CreateUser(c *gin.Context) { body := c.Request.Body bytes, err := ioutil.ReadAll(body) user := model.User{} json.Unmarshal(bytes, &user) if err != nil { panic(err) } res := impl.dao.CreateUser(c, user) c.JSON(200, map[string]interface{}{"code": 0, "msg": "", "count": 0, "data": res})}func (impl UserControllerImpl) FindUserByLoginNameAndPwd(c *gin.Context) { body := c.Request.Body bytes, err := ioutil.ReadAll(body) user := model.User{} json.Unmarshal(bytes, &user) if err != nil { panic(err) } userByLoginName := impl.dao.GetUserByLoginName(c, user.LoginName) //密码通过 if userByLoginName.Pwd == utils.GetMd5Str(user.Pwd) { setToken := auth.SetToken(c, utils.GetTokenStr(), user) c.JSON(200, map[string]interface{}{"code": 0, "msg": setToken, "count": 0, "data": utils.GetTokenStr()}) } else { if userByLoginName.Id == 0 { c.JSON(200, map[string]interface{}{"code": 0, "msg": "账号不存在", "count": 0, "data": "-1"}) } else { c.JSON(200, map[string]interface{}{"code": 0, "msg": "密码错误", "count": 0, "data": "-1"}) } }}func (impl UserControllerImpl) Register(c *gin.Context) { body := c.Request.Body bytes, err := ioutil.ReadAll(body) user := model.User{} json.Unmarshal(bytes, &user) if err != nil { panic(err) } user.Role = 1 res := impl.dao.CreateUser(c, user) c.JSON(200, map[string]interface{}{"code": 0, "msg": "", "count": 0, "data": res})}

router增加URL:

......userInfo := r.Group("/user"){ userInfo.POST("/save", controller.NewUserController().CreateUser) userInfo.POST("/login", controller.NewUserController().FindUserByLoginNameAndPwd) userInfo.POST("/register", controller.NewUserController().Register)}......

前端代码:

登录/注册

登录

3 小结

用户的登录和注册功能在一般情况下会使用到验证码,所以这里准备了一篇文章:​​一文搞懂Go整合captcha实现验证码功能​​,大家可以自行设计和补充哈。

除此之外,在系统的注册&登录功能背后,往往都会有系统的认证和授权,所以请大家耐心等待我的下一篇文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SVN 命令行获取提交日志
下一篇:数据库的最简单实现(数据库是如何实现的)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~