• 15. jwt认证中间件


    在上一篇登录功能的实现中,我们使用了jwt作为鉴权组件,其中登录后会颁发token。前端在访问后续请求时,可以带上这个token。对于一些需要权限校验的请求,我们就需要验证这个token,从token中获取到用户id(有了用户id,用户详情可以查DB)。

    此时我们很容易就想到了中间件,定义好鉴权中间件,对于需要鉴权的路由,加上这个中间件即可。

    直接上代码吧,注释非常清晰

    在这里插入图片描述

    middlewares/auth.go

    package middlewares
    
    import (
    	"bluebell/constdef"
    	"bluebell/controller"
    	"bluebell/pkg/jwt"
    	"strings"
    
    	"github.com/gin-gonic/gin"
    )
    
    // JWTAuthMiddleware 基于JWT的认证中间件
    func JWTAuthMiddleware() func(c *gin.Context) {
    	return func(c *gin.Context) {
    		// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
    		// 这里假设Token放在Header的Authorization中,并使用Bearer开头
    		// Authorization: Bearer xxxxxxx.xxx.xxx  / X-TOKEN: xxx.xxx.xx
    		// 这里的具体实现方式要依据你的实际业务情况决定,和前端对其即可
    		authHeader := c.Request.Header.Get("Authorization")
    		if authHeader == "" {
    			controller.ResponseError(c, controller.CodeNeedLogin)
    			c.Abort()
    			return
    		}
    		// 按空格分割
    		parts := strings.SplitN(authHeader, " ", 2)
    		if !(len(parts) == 2 && parts[0] == "Bearer") {
    			controller.ResponseError(c, controller.CodeInvalidToken)
    			c.Abort()
    			return
    		}
    		// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
    		mc, err := jwt.ParseToken(parts[1])
    		if err != nil {
    			controller.ResponseError(c, controller.CodeInvalidToken)
    			c.Abort()
    			return
    		}
    		// 将当前请求的userId信息保存到请求的上下文c上
    		c.Set(constdef.CtxUserIDKey, mc.UserID)
    
    		c.Next() // 后续的处理请求的函数中 可以用过c.Get(CtxUserIDKey) 来获取当前请求的用户信息
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    其中需要说明的一点是,将当前请求的userId信息保存到请求的上下文c上时,我们key用了一个全局变量,而不是一个写死的字符串userId,是因为后续其他接口需要从这个上下文中获取userId时也要用到这个变量,所以作为全局的较好。

    constdef/constdef.go

    package constdef
    
    const CtxUserIDKey = "userId"
    
    
    • 1
    • 2
    • 3
    • 4

    token中获取用户id一般都是controller层入口要做的事情,可能有很多接口需要从token获取用户id,所以可以封装一个函数

    controller/request.go

    package controller
    
    import (
    	"bluebell/constdef"
    	"errors"
    	"github.com/gin-gonic/gin"
    )
    
    var ErrorUserNotLogin = errors.New("用户未登录")
    
    // getCurrentUserID 获取当前登录的用户ID
    func getCurrentUserID(c *gin.Context) (userID int64, err error) {
    	uid, ok := c.Get(constdef.CtxUserIDKey)
    	if !ok {
    		err = ErrorUserNotLogin
    		return
    	}
    	userID, ok = uid.(int64)
    	if !ok {
    		err = ErrorUserNotLogin
    		return
    	}
    	return
    }```
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    Spark的Master、Worker、Dirver和Executor,对比Flink的Jobmanager、Taskmanager、Slot异同
    VMware打开共享虚拟机后找不到/mnt/hgfs/文件夹,以及不能拖拽/复制粘贴等操作,ubuntu不能安装VMware tools
    Windows下搭建GTK3开发环境
    MySQL数据库如何线上修改表结构
    机器学习中的二分类问题评价指标之精确率、召回率、F1值通俗理解
    Python编程从入门到实践 第六章:字典 练习答案记录
    10.9课上
    搭建Django项目
    JSP养猪信息管理系统myeclipse开发mysql数据库BS模式java编程网页结构
    联想图像国内首创 采用Oort生成式AI 引领智能客服新纪元
  • 原文地址:https://blog.csdn.net/YouMing_Li/article/details/136605199