热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

gin框架使用JWT鉴定权限

文章目录简介引入源码代码模型router中写法middlerware中写法ParseToken解析tokenstring*jwt.TokensecretKey密钥AuthClai

文章目录

  • 简介
  • 引入
  • 源码
  • 代码模型
  • router 中写法
  • middlerware 中写法
  • ParseToken 解析 token string => *jwt.Token
  • secretKey 密钥
  • AuthClaims 结构体
  • GenerateToken 生成 *jwt.Token
  • login 登录后响应头设置 COOKIE
  • 常规 HandlerFunc 使用用户信息


简介

目前主流的 gin 的鉴权框架有 github 上的 dgrijalva/jwt-go 和 golang-jwt/jwt,但是 dgrijalva/jwt-go 以前用的特别多,但是有一些漏洞,现在更推荐的是 golang-jwt/jwt 官方社区版

github:https://github.com/golang-jwt/jwt

官网:https://pkg.go.dev/github.com/golang-jwt/jwt/v4

JWT(JSON Web Tokens),

引入

go get -u github.com/golang-jwt/jwt

import "github.com/golang-jwt/jwt"

源码

// A JWT Token. Different fields will be used depending on whether you're
// creating or parsing/verifying a token.
type Token struct {Raw string // The raw token. Populated when you Parse a tokenMethod SigningMethod // The signing method used or to be usedHeader map[string]interface{} // The first segment of the tokenClaims Claims // The second segment of the tokenSignature string // The third segment of the token. Populated when you Parse a tokenValid bool // Is the token valid? Populated when you Parse/Verify a token
}

JWT 中的 token如上图,完整的 token 分为 3 部分

  • The first segment of the token:Header
  • The second segment of the token:Claims
  • The third segment of the token. Populated when you Parse a token:Signature

代码模型
  • 登录的 HandlerFunc 中,需要生成 token,并设置响应头带上这个 token
  • 中间件可以处理分组的请求,检测 Authorization 中数据做解析判定数据是否有效,如果无效直接返回无权限,不会进入到具体 HandlerFunc 中操作,如果有效则把 claims 中的用户信息保存到 gin.context 中,然后放行进入 HandlerFunc 中

router 中写法

r := gin.Default()authGroup := r.Group("/auth")// 分组使用 JWT 鉴权中间件
authGroup.Use(middleware.JWTAuth())

middlerware 中写法

中间件中做到解析 token,然后把 token 中的用户信息存放在 gin.Context 中,方便后面 HandlerFunc 中取用

// JWTAuth 鉴权中间件
func JWTAuth() gin.HandlerFunc {return func(c *gin.Context) {// 获取请求头中 token,实际是一个完整被签名过的 token;a complete, signed tokentokenStr := c.GetHeader("Authorization")if tokenStr == "" {c.JSON(http.StatusForbidden, "No token. You don't have permission!")c.Abort()return}// 解析拿到完整有效的 token,里头包含解析后的 3 segmenttoken, err := ParseToken(tokenStr)if err != nil {c.JSON(http.StatusForbidden, "Invalid token! You don't have permission!")c.Abort()return}// 获取 token 中的 claimsclaims, ok := token.Claims.(*AuthClaims)if !ok {c.JSON(http.StatusForbidden, "Invalid token!")c.Abort()return}// 将 claims 中的用户信息存储在 context 中c.Set("userId", claims.UserId)// 这里执行路由 HandlerFuncc.Next()}
}

ParseToken 解析 token string => *jwt.Token

// ParseToken 解析请求头中的 token string,转换成被解析后的 jwt.Token
func ParseToken(tokenStr string) (*jwt.Token, error) {// 解析 token string 拿到 token jwt.Tokenreturn jwt.ParseWithClaims(tokenStr, &AuthClaims{}, func(tk *jwt.Token) (interface{}, error) {return secretKey, nil})
}

secretKey 密钥

建议不要存放在项目代码中,要单独私有存放

var secretKey = []byte("some string")

AuthClaims 结构体

// AuthClaims 是 claims struct
type AuthClaims struct {UserId uint64 `json:"userId"`jwt.StandardClaims
}

GenerateToken 生成 *jwt.Token

一般在 login 后来生成 *jwt.Token 存放在响应头中给浏览器

// GenerateToken 一般在登录之后使用来生成 token 能够返回给前端
func GenerateToken(userId uint64, expireTime time.Time) (string, error) {// 创建一个 claimclaim := AuthClaims{UserId: userId,StandardClaims: jwt.StandardClaims{// 过期时间ExpiresAt: expireTime.Unix(),// 签名时间IssuedAt: time.Now().Unix(),// 签名颁发者Issuer: "abcnull",// 签名主题Subject: "gindemo",},}// 使用指定的签名加密方式创建 token,有 1,2 段内容,第 3 段内容没有加上noSignedToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)// 使用 secretKey 密钥进行加密处理后拿到最终 token stringreturn noSignedToken.SignedString(secretKey)
}

login 登录后响应头设置 COOKIE

login 登录之后需要把 token string 带到响应头中返回给前端浏览器来保存信息

// 查询数据库,通过用户密码拿到 userId
userId := 1// token 过期时间 60 天,Time 类型
var expireTime = time.Now().Add(60 * 24 * time.Hour)// 生成 token string
tokenStr, tokenErr := middleware.GenerateToken(userId, expireTime)
if tokenErr != nil {// todo: 做一些出错处理
}// 设置响应头信息的 token
c.SetCOOKIE("Authorization", tokenStr, 60, "/", "127.0.0.1", false, true)

常规 HandlerFunc 使用用户信息

// 登录之后可以接入 Get 拿到用户信息,返回是 (interface{}, bool)
userId, flag := c.Get("userId")// todo: 通过 userId 可以查询数据库获取想要的用户信息


推荐阅读
  • 命令模式是一种行为设计模式,它将请求封装成一个独立的对象,从而允许你参数化不同的请求、队列请求或者记录请求日志。本文将详细介绍命令模式的基本概念、组件及其在实际场景中的应用。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • Halcon之图像梯度、图像边缘、USM锐化
    图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像卷积:1.模糊2.梯度3.边缘4.锐化1.视频教程:B站、 ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在Django中提交表单时遇到值错误问题如何解决?
    在Django项目中,当用户提交包含多个选择目标的表单时,可能会遇到值错误问题。本文将探讨如何通过优化表单处理逻辑和验证机制来有效解决这一问题,确保表单数据的准确性和完整性。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • 通过使用七牛云存储服务,本文详细介绍了如何将本地图片高效上传至云端,并实现了内容的便捷管理。借助七牛云的 Python SDK,文章提供了从认证到文件上传的具体代码示例,包括导入必要的库、生成上传凭证以及处理文件路径等关键步骤。此外,还探讨了如何利用七牛云的 URL 安全编码功能,确保数据传输的安全性和可靠性。 ... [详细]
  • C语言中全部可用的数学函数有哪些?2.longlabs(longn);求长整型数的绝对值。3.doublefabs(doublex);求实数的绝对值。4.doublefloor(d ... [详细]
  • window下的python安装插件,Go语言社区,Golang程序员人脉社 ... [详细]
  • 在C++程序中,文档A的每一行包含一个结构体数据,其中某些字段可能包含不同数量的数字。需要将这些结构体数据逐行读取并存储到向量中,随后不仅在控制台上显示,还要输出到新创建的文档B中。希望得到指导,感谢! ... [详细]
author-avatar
最爱7色的彩虹
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有