Gin实战5:实现JWT中间件

一 开篇
- JWT核心优势:无状态设计、跨平台兼容性、自包含数据特性
- 典型应用场景:前后端分离架构、微服务鉴权、移动端API安全
二 Gin框架中间件开发实战
- 中间件架构设计
func JwtMiddleware(secret string) gin.HandlerFunc { return func(c *gin.Context) { // 令牌提取与验证逻辑 } }
- 核心功能实现
- 令牌提取策略:提取Header 中 Authorization 的值 Bearer+’ ‘+JWT
- 令牌解析验证:使用jwt.ParseWithClaims方法解析
- 上下文注入:将解析后的Claims存入context
- 错误处理规范
- 401响应标准化(JSON格式错误码)
- 异常场景覆盖:过期/篡改/格式错误令牌
三 增加白名单
- 实际开发中会有一部分API需要忽略JWT token验证,因此增加了白名单参数 最终代码如下:
func JwtMiddleware(writeList map[string]struct{}, secret string) gin.HandlerFunc {
return func(c *gin.Context) {
path := c.Request.URL.Path
if _, ok := writeList[path]; ok {
c.Next()
return
}
tokenHeader := c.GetHeader("Authorization")
if tokenHeader == "" || len(tokenHeader) < 7 || tokenHeader[:6] != "Bearer" {
c.AbortWithStatusJSON(401, gin.H{
"code": 401,
"message": "token invalid",
})
return
}
tokenString := tokenHeader[len("Bearer "):]
token, err := jwt.ParseWithClaims(tokenString, &biz.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
c.AbortWithStatusJSON(401, gin.H{
"code": 401,
"message": "token invalid",
})
return
}
if claims, ok := token.Claims.(*biz.CustomClaims); ok && token.Valid {
c.Set("user_id", claims.UserID)
c.Set("username", claims.Username)
} else {
c.AbortWithStatusJSON(401, gin.H{
"code": 401,
"message": "token invalid",
})
}
c.Next()
}
}
四 使用JWT中间件
- internal/routers/router.go 中使用中间件
mdls = append(mdls, middleware.JwtMiddleware(
map[string]struct{}{
"/v1/login": {},
},
conf.Jwt.Secret,
))
五 验证中间件是否生效
1、增加API
r.GET("/v1/get", account.GetUser)
2、返回context中取得到的用户信息
func (a *AccountServer) GetUser(context *gin.Context) {
userId, _ := context.Get("user_id")
username, _ := context.Get("username")
context.JSON(200, gin.H{
"user_id": userId,
"username": username,
})
}
3、使用 Apifox 请求时候增加Header 验证返回结果
六 总结
- jwt中的信息不是加密存储的,base64解析后可以看到明文信息,因此在记录敏感信息时建议进行加密处理
- 回复「Gin实战」获取代码
