手摸手,带你用Beego撸商城系列二(登录篇)

celverbamboo · · 1678 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

完整项目地址: [go-shop-b2c](https://github.com/CleverBamboo/go-shop-b2c) 系列文章: * [手摸手,带你用 Beego撸商城 系列一(基础篇)](https://cleverbamboo.github.io/2021/03/30/GO/手摸手,带你用Beego撸商城系列一(基础篇)/) * [手摸手,带你用 Beego撸商城 系列二(登录篇)](https://cleverbamboo.github.io/2021/04/01/GO/手摸手,带你用Beego撸商城系列二(登录篇)/) * [手摸手,带你用 Beego撸商城 系列三(系统配置篇)](https://cleverbamboo.github.io/2021/04/09/GO/手摸手,带你用Beego撸商城系列三(系统配置篇)/) ## 前言 一个商城后端系统,登录尤其重要,首先用户下单,需要登录,后台管理系统,需要登录。我们需要做的是,除了**登录以及注册**,其余的接口需要进行登录校验。 <!--more--> ## base_controller 封装 由于我们需要进行登录校验和不进行登录校验的 **Controller**,又由于 **base_controller** 需要进行登录检验,同时,不需要登录校验的 **Controller** 和 **base_controller**有共同的函数需要调用 综上所述,我们应该额外增加一个 **Controller** 分别用于 **base_controller** 继承 和 不需要登录检验的 **Controller** 用于继承 下面就简单地介绍一下 **json_controller** ### json_controller ```go type JsonController struct { beego.Controller } ``` * JsonResult 返回给前端JSON数据,公共调用函数 ```go /** * Ajax接口返回Json */ func (c *JsonController) JsonResult(status int, errCode int, errMsg string, data ...interface{}) { jsonData := make(map[string]interface{}, 3) jsonData["err_code"] = errCode jsonData["message"] = errMsg if len(data) > 0 && data[0] != nil { jsonData["data"] = data[0] } c.Ctx.Output.SetStatus(status) c.Data["json"] = jsonData c.ServeJSON() } ``` * ServerError 服务器通用报错 ```go /** * 服务器报错 */ func (c *JsonController) ServerError(err error) { c.Ctx.Output.SetStatus(http.GetHttpStatusByAlias("internalServerError")) logs.Error(err) } ``` * SetSessionUser 封装保存session的函数 ```go /** * 设置登录登录用户session信息 */ func (c *JsonController) SetSessionUser(member models.Member) { if member.Id <= 0 { c.DelSession(common.SessionName) c.DelSession("uid") c.DestroySession() } else { c.SetSession(common.SessionName, member) c.SetSession("uid", member.Id) } } ``` ## 登录检验 ### 在 beego 的 Prepare 函数调用 简单说一下Prepare函数的作用,这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些 Method 方法之前执行,用户可以重写这个函数实现类似用户验证之类。[点击跳转文档查看方法](https://beego.me/docs/mvc/controller/controller.md) 主要做三件事 1. **gob** 序列化保存用户信息 ps: 序列化某个对象,必须在 **encoding/gob** 编码解码前进行注册 2. 从 **session** 中获取用户信息 3. 如果 **Cookie** 中存在登录信息,从 **cookie** 中获取用户信息 ## 在其它 Controller 基本写法 主要分类,需要登录检验和不需要登录检验的 **Controller**,不需要登录校验通常是包含登录和注册的 **Controller** ### 需要登录检验的 Controller编写 以 **address_controller** 为例 截取部分代码 ```go // 需要登录校验就需要继承 BaseController,这样该 Controller下的函数都在调用执行之前到 执行Prepare函数进行登录检验 type AddressController struct { BaseController } // URLMapping ... func (c *AddressController) URLMapping() { c.Mapping("AddAddress", c.AddAddress) c.Mapping("DeleteAddress", c.DeleteAddress) c.Mapping("UpdateAddress", c.UpdateAddress) c.Mapping("GetAllAddress", c.GetAllAddress) } // @Title 新增地址 // @router /add [post] func (c *AddressController) AddAddress() { var address model_views.Receiver if v := c.GetString("address"); v != "" { _ = json.Unmarshal([]byte(v), &address) } var receiver models.Receiver receiver.Id = address.Id receiver.Consignee = address.Consignee receiver.AreaName = address.AreaName receiver.AreaId = address.AreaId receiver.Address = address.Address receiver.IsDefault = address.IsDefault receiver.Phone = address.Phone receiver.ZipCode = address.ZipCode receiver.MemberId = int64(c.Member.Id) receiver.LastUpdatedBy = c.Member.Username _, err := models.AddReceiver(&receiver) if err != nil { // 服务通用报错函数调用 c.ServerError(err) return } c.JsonResult(http.GetHttpStatusByAlias("created"), http.ErrOK, http.Success, nil) } ``` 就是这么简单,其它 **Controller** 基本都是如此 ### 不需要登录检验的 Controller 编写 截取部分代码 ```go // 继承 JsonController,不会调用 BaseController 的Prepare函数进行登录校验 type UserController struct { JsonController } // @Title 登录 // @router /login [post] func (c *UserController) Login() { var mobile string var sms string // mobile if v := c.GetString("mobile"); v != "" { mobile = v } // sms if v := c.GetString("sms"); v != "" { sms = v } smsModel, err := models.GetSmsByCodeAndMobile(sms, mobile) if err != nil { c.JsonResult(http.GetHttpStatusByAlias("ok"), http.ErrError, http.Fail, "手机和验证码不匹配") return } if smsModel.ExpireDate != nil { c.JsonResult(http.GetHttpStatusByAlias("ok"), http.ErrError, http.Fail, "验证码已过期") return } if smsModel.IsUsed == 1 { c.JsonResult(http.GetHttpStatusByAlias("ok"), http.ErrError, http.Fail, "验证码已使用") return } member, _ := models.GetMemberByUsername(mobile) if member == nil { member = &models.Member{} } if member.Id > 0 { // 最后登录IP member.LoginIp = c.Ctx.Input.IP() member.LoginDate = time.Now() err = models.UpdateMemberById(member) if err != nil { c.ServerError(err) return } } else { member.Username = mobile member.Mobile = mobile member.MemberRankId = 1 // 普通会员 _, err := models.AddMember(member) if err != nil { c.ServerError(err) return } } /** * 更新短信使用 */ now := time.Now() smsModel.UsedDate = &now smsModel.IsUsed = 1 err = models.UpdateSmsById(smsModel) if err != nil { c.ServerError(err) return } /** * 设置Cookie */ c.SetSessionUser(*member) var cookieMember CookieMember cookieMember.MemberId = member.Id cookieMember.Username = member.Username cookieMember.Time = time.Now() v, err := helpers.Encode(cookieMember) if err == nil { c.SetSecureCookie(common.AppKey(), "web_login", v, 24*3600) } commonController := &CommonController{} memberView := commonController.setMemberByMemberModel(*member) c.JsonResult(http.GetHttpStatusByAlias("ok"), http.ErrOK, http.Success, memberView) } ``` ## 总结 最后,写完这两个基础的 **Controller** 后,基本就是根据业务判断是否需要登录校验,然后就行CRUD(增删改查)的业务编写就好了,没错就是这么简单

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1678 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传