Beego 用户登陆、注册、注销、密码加密(Model模型、Session保持登陆状态、Valid包表单汉化和自定义验证) 您所在的位置:网站首页 报价系统状态验证中不包括 Beego 用户登陆、注册、注销、密码加密(Model模型、Session保持登陆状态、Valid包表单汉化和自定义验证)

Beego 用户登陆、注册、注销、密码加密(Model模型、Session保持登陆状态、Valid包表单汉化和自定义验证)

2024-07-11 16:35| 来源: 网络整理| 查看: 265

Beego 用户Controller控制器、Router路由简单完整示例(登陆、注册、注销、Model模型、Session保持登陆状态、Valid包表单汉化和自定义验证) 一、前言1、系统环境 二、路由Router三、用户模型Model四、用户状态控制器UserStatusController1、结构体2、方法 五、登陆控制器LoginController1、结构体2、方法 六、注册控制器UserRegisterController1、结构体2、方法 七、注销控制器UserLogoutController1、结构体2、方法 八、表单验证1、汉化Valid包2、自定义User表单验证 九、util.CreateMsg

一、前言

我太难了 目前网上找得相关Beego资料大部分都不完整和比较陈旧,因为项目需要,编写了一个简单的用户流程,如果能帮到您的话,可以点个收藏支持一下。以下内容不包括数据库模型的创建等基础操作。车轮滚滚,知识无价。

1、系统环境 Beego : 1.12.0 GoVersion : go1.12.9 二、路由Router

路径:项目/routers/user.go

package routers import ( "github.com/astaxie/beego" "项目/controllers" ) func init() { // 登陆路由 beego.Router("/user/login/", &controllers.UserLoginController{}) // 注销路由 beego.Router("/user/logout/", &controllers.UserLogoutController{}) // 注册路由 beego.Router("/user/register/", &controllers.UserRegisterController{}) } 三、用户模型Model

路径: 项目/model/user.go

type User struct { Id int Username string // 用户名 Password string // 密码 CreateTime time.Time `orm:"auto_now_add;type(datetime)"` // 创建时间 } 四、用户状态控制器UserStatusController 1、结构体

路径:项目名/controller/user.go

type UserStatusController struct { beego.Controller isLogin bool // 登陆状态标记 User models.User // 登陆的用户 } 2、方法

这里重写的是对象的 Prepare 方法,这样可以在其他控制器继承该方法来判断用户是否已经登陆,实现 保持登陆状态 功能。

func (c *UserStatusController) Prepare() { // 设置默认值 c.isLogin = false c.Data["isLogin"] = false c.User = models.User{} // 获取Session信息 - 注意这里返回的是interface类型 useridInterface := c.GetSession("userid") userid, ok := useridInterface.(int) // 优化性能,如果Id不存在就不需要再获取Password if !ok { return } // 接下来是验证Password是否被更新 - 防止数据库密码更新后仍保持Session passwordInterface := c.GetSession("password") password, _ := passwordInterface.(string) user := models.User{Id: userid} // ORM对象 o := orm.NewOrm() // 这里如果在其他地方没有用到用户其他字段的话 // 建议改成One方法仅返回密码来判断 // 即 o.QueryTable("user").Filter("id", &user.id).One(&user,"password") err := o.Read(&user) // 如果无法读取到用户就结束 if err != nil { return } // 判断密码是否修改过 err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) if err != nil { return } // 最后才设置登陆状态 c.isLogin = true c.Data["isLogin"] = true c.User = user } 五、登陆控制器LoginController

路径:项目名/controller/user.go

1、结构体

继承于UserStatusController ,实现检查用户是否已经登陆,防止重复登陆。

type UserLoginController struct { UserStatusController } 2、方法

表单提交使用 POST 方法

func (c *UserLoginController) Post() { // 创建logs(记录器) l := logs.BeeLogger{} l.SetPrefix("用户登陆API:") // 判断是否已经登陆 - 已登陆就终结登陆流程 if c.isLogin == true { l.Debug("用户已登陆") c.Ctx.ResponseWriter.WriteHeader(202) // util.CreateMsg - 这个是我自己写的方法,请参考我博文下面的源代码 c.Data["json"] = util.CreateMsg(202, "用户已登陆") c.ServeJSON() return } // 用户登陆 username := strings.TrimSpace(c.GetString("username")) password := strings.TrimSpace(c.GetString("password")) // 验证表单数据 - 这里使用官方表单数据验证包(结合自定义验证) // github.com/astaxie/beego/validation // 可以下面附加的验证工具,或者直接把这一段删掉 u := &valid.ValidateUser{ Username: username, Password: password, } err := u.ValidUser() if err != nil { l.Debug("用户注册失败,原因:%s", err.Error()) c.Ctx.ResponseWriter.WriteHeader(403) c.Data["json"] = util.CreateMsg(403, err.Error()) c.ServeJSON() return } // 创建User对象 - 不设置密码 user := models.User{Username: username} // 创建ORM对象 o := orm.NewOrm() // 读取用户对象 - 这里使用One方法而不使用Read可以避免读取整个User对象,稍微优化 // 虽然在这里没有什么卵用,但是如果用户模型比较复杂的情况下还是有效果的 err = o.QueryTable("user").Filter("username", &user.Username).One(&user, "id","password") if err != nil { l.Debug("用户不存在") c.Ctx.ResponseWriter.WriteHeader(401) c.Data["json"] = util.CreateMsg(401, "用户不存在") c.ServeJSON() return } // 验证用户密码 // 第一个参数是数据库存储的加密密码,第二个参数是原密码 // 密码是单方面加密,不可解密 // bcrypt包提供的安全加密可以应对大部分的安全要求,具体实现细节请自行百度 err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) if err != nil { l.Debug("用户密码错误") c.Ctx.ResponseWriter.WriteHeader(401) c.Data["json"] = util.CreateMsg(401, "密码错误") c.ServeJSON() return } // 设置服务器Session存储 c.SetSession("userid", user.Id) c.SetSession("password", password) // 这里存储的是原始密码 // 返回成功信息 c.Data["json"] = util.CreateMsg(200, "用户登陆成功") c.ServeJSON() } 六、注册控制器UserRegisterController

路径:项目名/controller/user.go

注册功能只是简单演示,这里直接在App.conf(项目配置文件)里面添加了一个配置参数registertoken ,实现内部注册验证,如果要使用邮箱注册请自己再琢磨一下,注册环节

1、结构体

因为注册不需要验证是否已经登陆,直接继承beego原本的控制器就好了。如果需要验证登陆状态的话,直接改成继承UserStatusController 然后像登陆一样,判断 c.isLogin 是否为真,然后return就好。

type UserRegisterController struct { beego.Controller } 2、方法

表单提交使用 POST 方法

func (c *UserRegisterController) Post() { l := logs.GetBeeLogger() l.SetPrefix("用户注册API:") // 内部用户注册 // 获取Post表单数据 registerToken := strings.TrimSpace(c.GetString("token")) // 验证Token - 这里是在App.conf里面设置的registertoken if registerToken != beego.AppConfig.String("registertoken") { l.Debug("注册测试Token验证失败,用户输入:%s,系统环境设置:%s", registerToken, beego.AppConfig.String("registertoken")) c.Ctx.ResponseWriter.WriteHeader(403) // util.CreateMsg - 这个是我自己写的方法,请参考我博文下面的源代码 c.Data["json"] = util.CreateMsg(403, "token验证失败") c.ServeJSON() return } // 获取表单数据 - 去除两边的空格 username := strings.TrimSpace(c.GetString("username")) password := strings.TrimSpace(c.GetString("password")) // 验证表单数据 - 这里使用官方表单数据验证包(结合自定义验证) // github.com/astaxie/beego/validation // 可以下面附加的验证工具,或者直接把这一段删掉 u := &valid.ValidateUser{ Username: username, Password: password, } err := u.ValidUser() if err != nil { l.Debug("用户注册失败,原因:%s", err.Error()) c.Ctx.ResponseWriter.WriteHeader(403) c.Data["json"] = util.CreateMsg(403, err.Error()) c.ServeJSON() return } // 生成加密密码 - 这里使用了Golang官方加密包 // golang.org/x/crypto/bcrypt // 注意 - 每次生成的密码都不一样,但是没关系 // 登陆是验证原密码再加密后是否能和存储的加密是否一致 // bcrypt.DefaultCost = 10 encodePW, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { l.Debug("密码加密失败", err) c.Ctx.ResponseWriter.WriteHeader(500) c.Data["json"] = util.CreateMsg(500, "密码生成失败") c.ServeJSON() return } // 创建User对象 user := models.User{Username: username, Password: string(encodePW)} // 创建ORM对象 o := orm.NewOrm() // ReadOrCreate - 先读取再创建 status, id, err := o.ReadOrCreate(&user, "username") // 数据库操作失败 if err != nil { l.Error("发生错误:%s", err) c.Ctx.ResponseWriter.WriteHeader(500) c.Data["json"] = util.CreateMsg(500, "数据库连接失败,用户注册失败。") c.ServeJSON() return } // 创建失败 - 用户名已经存在 if !status { l.Debug("用户名已经存在,id为%d", id) c.Ctx.ResponseWriter.WriteHeader(403) c.Data["json"] = util.CreateMsg(403, "用户注册失败:用户已存在") c.ServeJSON() return } // 如果需要注册后直接保持登陆状态 // 设置服务器Session存储 // c.SetSession("userid", user.Id) // c.SetSession("password", password) // 这里存储的是原始密码 // 创建用户成功 - 返回用户名 c.Data["json"] = util.CreateMsg(200, fmt.Sprintf("用户%s注册成功", username)) c.ServeJSON() } 七、注销控制器UserLogoutController

路径:项目名/controller/user.go

1、结构体

继承 UserStatusController 来判断用户的登陆状态

type UserLogoutController struct { UserStatusController } 2、方法 func (c *UserLogoutController) Get() { // 用户注销 if !c.isLogin { c.Ctx.ResponseWriter.WriteHeader(403) // util.CreateMsg - 这个是我自己写的方法,请参考我博文下面的源代码 c.Data["json"] = util.CreateMsg(403, "用户未登陆") c.ServeJSON() return } // 删除Session - session删除后就不能使用 UserStatusController的 Prepare // 来保持登陆状态,即实现注销方法 c.DestroySession() c.Data["json"] = util.CreateMsg(200, "用户注销成功") c.ServeJSON() } 八、表单验证

表单验证参考了 fengke549015 的 beego validate验证包的修改原有验证提示信息与使用自定义函数验证的方法 ,非常感谢。这里用简便的方式来实现Valid包的提示信息汉化。

1、汉化Valid包

路径:项目/valid/init.go

package valid import ( "github.com/astaxie/beego/validation" "reflect" ) func init() { // 汉化官方Validation var MessageTmpls = map[string]string{ "Required": "不能为空", "Min": "最小为 %d", "Max": "最大为 %d", "Range": "范围在 %d 至 %d", "MinSize": "最小长度为 %d", "MaxSize": "最大长度为 %d", "Length": "长度必须是 %d", "Alpha": "必须是有效的字母字符", "Numeric": "必须是有效的数字字符", "AlphaNumeric": "必须是有效的字母或数字字符", "Match": "必须匹配格式 %s", "NoMatch": "必须不匹配格式 %s", "AlphaDash": "必须是有效的字母或数字或破折号(-_)字符", "Email": "必须是有效的邮件地址", "IP": "必须是有效的IP地址", "Base64": "必须是有效的base64字符", "Mobile": "必须是有效手机号码", "Tel": "必须是有效电话号码", "Phone": "必须是有效的电话号码或者手机号码", "ZipCode": "必须是有效的邮政编码", } if len(MessageTmpls) == 0 { return } // 替换原本的 MessageTmpls,有兴趣的直接看一下源代码,要注意import的顺序。 for k, _ := range MessageTmpls { validation.MessageTmpls[k] = MessageTmpls[k] } } // 这里将 fengke549015 中获取Alias的方法提取出来,个人感觉更优雅,如果其他 // 自定义验证需要使用该方法,可以直接调用 func GetAlias(i interface{}, field string) (alias string) { // 获取字段名 // i - 结构体 // field - 字段名 st := reflect.TypeOf(i) filed, _ := st.FieldByName(field) return filed.Tag.Get("alias") }

然后在 main.go 中 import 加入valid模块的初始化可以了,个人感觉比 fengke549015 的方法优雅一点。

import ( "github.com/astaxie/beego" _ "项目/models" _ "项目/routers" _ "项目/valid" // 就是这玩意 ) 2、自定义User表单验证

路径: 项目/valid/user.go

type ValidateUser struct { Username string `alias:"用户名" valid:"Required;MinSize(3);MaxSize(20)"` Password string `alias:"密码" valid:"Required;MinSize(3);MaxSize(20)"` } func (u *ValidateUser) ValidUser() (err error) { // 先创建一个Validation valid := validation.Validation{} // 验证传入的User信息 status, _ := valid.Valid(u) // 如果验证失败 if !status { for _, err := range valid.Errors { // 获取字段别称 var alias = GetAlias(ValidateUser{}, err.Field) // 返回验证的错误信息 return errors.New(alias + err.Message) } } return nil } 九、util.CreateMsg

这个方法其实就是返回 Json 内容,具体实现细节比较基础,百度比较详细,下面是源代码。

路径: 项目/util/msg.go

package util // Json信息返回模版 type JsonMsg struct { Code int Msg string } func CreateMsg(code int, msg string) (m *JsonMsg) { m = &JsonMsg{ Code: code, Msg: msg, } return }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有