本文核心内容是利用 jwt-go 中间件来开发 golang webapi 用户登陆模块的 token 下发和验证, 小程序登陆功能只是一个切入点, 这套逻辑同样适用于其他客户端的登陆处理
小程序登陆逻辑
小程序的登陆逻辑在其他博主的文章中已经总结得非常详尽, 比如我参考的是这篇博文: 微信小程序登录逻辑整理, 所以在这里不再赘述, 只是大致归纳一下我的实现流程:
在小程序端调用 wx.login 方法, 异步获得到微信下发的 jscode , 然后将 jscode 发送到 golang 服务端 (如果需要详细用户信息, 见参考博文的实现逻辑, 流程大致相似);
服务端接收到 jscode 后, 将其与 AppID 和 AppSecret 一起按官方文档的格式, 发送到微信接口 ( AppID 和 AppSecret 在小程序管理平台上进行查看), 如果接口调用成功, 会返回以下字段:
openid: 用户信息唯一识别 id
session_key : 解密用户信息的 key
expires_in :key 的有效期
根据 open_id 去数据库查找对应的用户信息, 如果有, 获得其平台 uid , 否则新建用户, 返回新建信息 uid ;
将 uid 作为关键信息, 生成 jwt 格式的 token 字符串, 返回给小程序客户端, 小程序收到 token 判定登陆成功, 并将 token 存入 localstorage , 以后的每次请求先读取 localstorage 中的 token 放入请求头部作为身份标识, 如果 token 失效或者无法读取, 则重新执行登陆流程
由于小程序段逻辑简单, 而且不是本文讨论重点, 代码实现就不贴出了, 后面应该也不会再补
服务端处理流程
服务端实现是本文的重头戏, 由于 golang 语言的特性, 我在实际开发中也踩了一些不大不小的坑, 在这里进行详细记录, 也作为一个经验总结, 同时加深印象服务端流程可以大致分为以下几个大步骤:
根据客户端发送的 jscode 获得用户 open_id
利用 open_id 获取平台 uid , 同时使用 jwt-go 中间件实现 token 的生成
封装 token 验证中间件, 判断请求是否合法
本文的代码实现是在 gin 框架基础上完成的, gin 是一个非常轻量的 web http 处理框架, 很符合 golang 轻框架的理念, 但高度灵活也要求了一定的自主开发能力, 比如请求数据库读写请求信息读取和一些中间件的使用, 这些都需要自己查找不同包的官方文档, 去检索 Api 和查找对应的解决方案虽然如此, 但作为习惯了 .net 平台 高度封装和甜到发腻的语法糖的 .neter , 在 golang 开发过程中也体会到了不一样的乐趣废话不多说, 如果对 golang 开发感兴趣的话, gin 是一个我十分推荐的上手框架
获得用户 open_id
在这里简单介绍一下路由 model 和 controller 的一个分层开发实现:
main.go 程序入口, 在这里进行路由分发
controllers/xx.go xx 模块的路由请求处理代码相关
models/xx.go xx 模块用到的结构体 struct (类似 class) 定和结构体相关函数定义
middleware 存放封装后的请求处理中间件
首先, 按照 gin 框架的基础路由处理, 调用 AccountController 中的 WxLogin 函数, 接受处理 / account/login 路由的 GET 请求
- //main.go
- ...
- func main(){
- r := gin.Default()
- account := new(controllers.AccountController)
- r.GET("/account/login", account.WxLogin)
- }
然后在
AccountController.go
中先读取 jscode , 再将 jscode 和其他信息一起发送给微信服务器, 获得官方返回的核心字段
- //controllers/AccountController.go
- ...
- func (ctrl AccountController) WxLogin(c *gin.Context) {
- jscode := c.Query("jsCode")
- // 发送 jscode, 获得用户的 open_id
- wxSession, err := accountModel.WxLogin(jscode)
- ...
- }
未完待续
来源: http://www.bubuko.com/infodetail-2542428.html