全站之路一路坑beego

beego项目实战——注册和登录

2020-03-31  本文已影响0人  血之君殇

上一篇里完成了短信验证码的生成,这一篇里就完成短信验证码的校验,以及后续的登录和注册功能

model

login.go

type Login struct {
    Mobile string
    Vcode  string
}

登录的model,需要手机号和短信验证码
user.go

type User struct {
    Id     int64
    Mobile string `orm:"size(11)"`
    Type   int    `orm:"size(1)"`
}

func init() {
    orm.RegisterModel(new(User))
}

// 根据手机号获取或注册用户
func GetUserByMobile(mobile string) (id int64, err error) {
    o := orm.NewOrm()
    user := User{Mobile: mobile}
    _, id, err = o.ReadOrCreate(&user, "Mobile")
    return id, err
}

此处涉及到orm的问题了,众所周知,与orm的话写代码会方便很多,性能没达到瓶颈的话orm还是很好用的
Id字段生成数据库时会自动变为主键和自增,不要相信golint的鬼话写成ID
orm.RegisterModel(new(User))这句放在init函数中用来在一开始注册模型
ReadOrCreate()尝试从数据库读取,不存在的话就创建一个,这样当用户没有注册的话就相当于直接注册了,该函数返回值分别为是否是新创建的,创建的id,错误

自动生成数据库

main.go

func init() {
    // set default database
    orm.RegisterDataBase("default", "mysql", beego.AppConfig.String("sqlconn"), 30)

    // create table
    orm.RunSyncdb("default", false, true)
}

在main.go的init中设计数据库的连接和自动创建表
beego.AppConfig.String会读取config/app.conf中的配置文件
orm.RunSyncdb("default", false, true)设置创建表的规则,三个参数分别为数据库别名,是否先drop再建表,是否打印执行过程

建表
运行的时候就会看到如图所示的建表语句

controller

// @Title Login
// @Description 登录
// @Param body body models.Login true "登录信息"
// @Success 200 {int} 用户id
// @Failure 400 {string} 验证码错误
// @Failure 500 {string} 服务器错误
// @router / [post]
func (l *LoginController) Post() {
    var login models.Login
    json.Unmarshal(l.Ctx.Input.RequestBody, &login)
    vcode := string(models.Redis.Get(login.Mobile).([]byte))
    if login.Vcode != vcode {
        l.Data["json"] = "验证码错误"
        l.Abort("400")
    }
    id, err := models.GetUserByMobile(login.Mobile)
    if err != nil {
        l.Data["json"] = err.Error()
        l.Abort("500")
    }
    l.SetSession("uid", id)
    l.Data["json"] = id
    l.ServeJSON()
}

使用string(models.Redis.Get(login.Mobile).([]byte))来获取存储在redis中的验证码,此处有坑,redis封装的get取出来是个interface{},需要先转成字节数组,再转成字符串才能用,你说这玩意整的
models.GetUserByMobile查询用户是否存在,不存在则创建一个
SetSession用来记录登录态,单机版的直接就用session就好,response里会带着setcookie命令

router

beego.NSNamespace("/login",
    beego.NSInclude(
        &controllers.LoginController{},
    ),
),

效果

登录接口

验证登录态

还有很重要的一步就是登录了之后要验证登录态,这个涉及的东西就比较复杂了,需要用过滤器来实现
main.go

var FilterUser = func(ctx *context.Context) {
    _, ok := ctx.Input.Session("uid").(int)
    if !ok {
        var whiteMap map[string]int
        whiteMap = make(map[string]int)
        whiteMap["/v1/login"] = 1
        whiteMap["/v1/captcha"] = 1
        whiteMap["/v1/sms"] = 1
        if _, ok = whiteMap[ctx.Request.RequestURI]; !ok {
            ctx.ResponseWriter.WriteHeader(401)
            ctx.WriteString("未登录")
            return
        }
    }
}
beego.InsertFilter("/v1/*", beego.BeforeRouter, FilterUser)

这里又有一个大坑,要自己引入"github.com/astaxie/beego/context",否则IDE会自动引入一个context,导致代码报错,官方文档上也没说,往死里坑人
使用map创建一个白名单,将两个验证码接口和一个登录接口豁免掉
判断用户未登录之后直接return就可以组织后续的函数执行了

上一篇下一篇

猜你喜欢

热点阅读