【go商城】gin+mysql实现token登陆校验

Cookie,Session,Token这些用于认证,鉴权的名词相信大家都很熟悉了,网上都有大量的文章讲解,这里我们主要针对本商城通过mysql进行存储的token鉴权进行讲解。

这只是作为一个学习项目使用Mysql进行存储鉴权信息,一般企业项目中的单点登录都会使用redis进行存储

什么是token

访问资源接口(API)时所需要的资源凭证
简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)

特点

服务端无状态化、可扩展性好
支持移动端设备
安全
支持跨程序调用

token 的身份验证流程:
[图片上传失败...(image-5d8906-1655621934648)]
token的解释,转自https://juejin.cn/post/6844904034181070861

商城中token存储

新蜂商城项目中存在两个类型的用户:

  1. 后台管理员
  2. 商城用户

其实现逻辑是一致的所以我们调一个讲解即可,这里我们使用后台管理员的登陆进行讲解

我们使用了两张数据库表对用户的登录进行管理

tb_newbee_mall_admin_user & tb_newbee_mall_admin_user_token

我们通过两张表的admin_user_id将 用户和token进行了关联,如果用户登陆状态是有效的,则tb_newbee_mall_admin_user_token中就会存在一条记录,否则就是用户没有登陆。
[图片上传失败...(image-f954ca-1655621934649)]

[图片上传失败...(image-49b31-1655621934649)]

gin实现接口鉴权

管理员登录的时候,校验用户名和密码,通过的话则将生成的token存入数据库中用于后续的鉴权

// AdminLogin 管理员登陆
func (m *ManageAdminUserService) AdminLogin(params manageReq.MallAdminLoginParam) (err error, mallAdminUser manage.MallAdminUser, adminToken manage.MallAdminUserToken) {
    err = global.GVA_DB.Where("login_user_name=? AND login_password=?", params.UserName, params.PasswordMd5).First(&mallAdminUser).Error
    if mallAdminUser != (manage.MallAdminUser{}) {
        token := getNewToken(time.Now().UnixNano()/1e6, int(mallAdminUser.AdminUserId))
        global.GVA_DB.Where("admin_user_id", mallAdminUser.AdminUserId).First(&adminToken)
        nowDate := time.Now()
        // 48小时过期
        expireTime, _ := time.ParseDuration("48h")
        expireDate := nowDate.Add(expireTime)
        // 没有token新增,有token 则更新
        if adminToken == (manage.MallAdminUserToken{}) {
            adminToken.AdminUserId = mallAdminUser.AdminUserId
            adminToken.Token = token
            adminToken.UpdateTime = nowDate
            adminToken.ExpireTime = expireDate
            if err = global.GVA_DB.Create(&adminToken).Error; err != nil {
                return
            }
        } else {
            adminToken.Token = token
            adminToken.UpdateTime = nowDate
            adminToken.ExpireTime = expireDate
            if err = global.GVA_DB.Save(&adminToken).Error; err != nil {
                return
            }
        }
    }
    return err, mallAdminUser, adminToken

}

然后我们定义一个拦截器,让需要鉴权的接口进行token的校验

// 拦截器
func AdminJWTAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.Request.Header.Get("token")
        if token == "" {
            response.FailWithDetailed(nil, "未登录或非法访问", c)
            c.Abort()
            return
        }
        err, mallAdminUserToken := manageAdminUserTokenService.ExistAdminToken(token)
        if err != nil {
            response.FailWithDetailed(nil, "未登录或非法访问", c)
            c.Abort()
            return
        }
        if time.Now().After(mallAdminUserToken.ExpireTime) {
            response.FailWithDetailed(nil, "授权已过期", c)
            manageAdminUserTokenService.DeleteMallAdminUserToken(token)
            c.Abort()
            return
        }
        c.Next()
    }

}

最后在我们需要使用鉴权的接口处注册上这个拦截器的中间件,不需要鉴权的接口就不使用拦截器

func (r *ManageAdminUserRouter) InitManageAdminUserRouter(Router *gin.RouterGroup) {
    mallAdminUserRouter := Router.Group("v1").Use(middleware.AdminJWTAuth())
    mallAdminUserWithoutRouter := Router.Group("v1")
    var mallAdminUserApi = v1.ApiGroupApp.ManageApiGroup.ManageAdminUserApi
    {
        mallAdminUserRouter.POST("createMallAdminUser", mallAdminUserApi.CreateAdminUser) // 新建MallAdminUser
        mallAdminUserRouter.PUT("adminUser/name", mallAdminUserApi.UpdateAdminUserName)   // 更新MallAdminUser
        mallAdminUserRouter.PUT("adminUser/password", mallAdminUserApi.UpdateAdminUserPassword)
......
    }
    {
        mallAdminUserWithoutRouter.POST("adminUser/login", mallAdminUserApi.AdminLogin) //管理员登陆
    }
}

因为这里我们没有使用到更高级别的权限管理,go中对于权限管理有casbin这个库,有兴趣的话可以了解一下,这里不做过多的讲解。

效果演示

启动我们后管系统的vue项目,登陆后发现tb_newbee_mall_admin_user_token 表中新增了一条token的数据,同时前端的请求头中也会新增一个token的字段,用于存储鉴权信息。


token.png

总结

如果你对这一节的内容感兴趣可以访问https://github.com/newbee-ltd/newbee-mall-api-go/ 下载源代码,后续一章我会介绍跨域相关的内容,当时进行调试前端项目的时候也是被自己坑惨了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容