美文网首页全站之路一路坑beego
beego项目实战——注册和登录

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

作者: 血之君殇 | 来源:发表于2020-03-31 14:44 被阅读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就可以组织后续的函数执行了

    相关文章

      网友评论

        本文标题:beego项目实战——注册和登录

        本文链接:https://www.haomeiwen.com/subject/imhwuhtx.html