Go语言中JWT的创建和解析操作详解

 更新时间:2023年05月19日 08:57:20   作者:三杯温开水  
JWT的全名是Json web token,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,这篇文章主要介绍了在Go语言中JWT的创建和解析操作,感兴趣的同学可以参考下文

JWT介绍

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。下面就以一个标准的jwt功能实现方式进行编码。并且这个jwt也会相对安全一点,因为是有加密过的。一般用户登录后生成的token都是需要进行加密的,每一次访问,服务端都会根据前端的请求做出对应的策略,避免一定的非必要脚本攻击。

JWT相对于Cookie和Session的优点

Cookie和Session存放在哪,相对于JWT有啥区别?

Cookie是储存在客户端的,Session是储存在服务端的。

Cookie:

1、客户端请求服务器后,如果服务器需要记录用户状态,服务器会在响应信息中包含一个Set-Cookie的响应头

2、客户端会根据这个响应头存储Cookie信息。再次请求服务器时,客户端会在请求信息中包含一个Cookie请求头。

Session:

反正就是服务端生成,存储在服务器的内存中以及保存在文件或数据库中,返回给前端储存到cookie中

1、session是有过期时间的,可以设置过期时间或者服务器关闭就会消失

2、session多了服务端会有内存压力,这就需要负载均衡了以及不同服务器的session共享问题。

JWT:

1、 在头部信息中声明加密算法和常量, 然后把header使用json转化为字符串

2、在载荷中声明用户信息,同时还有一些其他的内容;再次使用json 把载荷部分进行转化,转化为字符串 (但是你觉得载荷中应不应该放置敏感的信息,当然不行,因为有效载荷中的内容是base64进行编码的,并不是进行加密的,而且JWT存储在localstorage等等,能够被获取到)

3、 使用在header中声明的加密算法和每个项目随机生成的secret来进行加密, 把第一步分字符串和第二部分的字符串进行加密, 生成新的字符串。此字符串是独一无二的。

4、解密的时候,只要客户端带着JWT来发起请求,服务端就直接使用secret进行解密。

你可以这样理解,JWT不受浏览器之间的令牌约束,并且其是有加密的,可以一定程度上得到保护。

 第一部分为头部(header),第二部分我们称其为载荷(payload),第三部分是签证(signature)。

实现jwt

引入jwt-go

我们需要先引入这个go-jwt

go get "github.com/dgrijalva/jwt-go"

创建一个jwt.go

jwt.StandardClaims 中有很多参数,可以根据自己的需要进行添加,可以查看源码

// 设置token过期时间
const TokenExpireDuration = time.Hour * 2
var mySecret = []byte("努力学习go语言")
// 这里可以根据自己的业务做出更改
type MyClaims struct {
	UserID   int64  `json:"user_id"`
	UserName string `json:"user_name"`
	jwt.StandardClaims
}
// GenToken 生成JWT
func GenToken(userId int64, username string) (string, error) {
	// 创建我们自己声明的数据
	c := MyClaims{
		userId,
		username, // 定义字段
		jwt.StandardClaims{
			IssuedAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
			Issuer:   "三杯温开水",                                 // 签发人
		},
	}
	// 使用指定的签名方法创建签名对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	// 返回token
	return token.SignedString(mySecret)
}
// ParseToken 解析 JWT
func ParseToken(tokenString string) (*MyClaims, error) {
	mc := new(MyClaims)
	// 解析token
	token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
		return mySecret, nil
	})
	if err != nil {
		return nil, err
	}
	if token.Valid { // 校验token
		return mc, nil
	}
	return nil, errors.New("invalid token")
}

创建一个jwt的中间件

这个中间件一般会放置在需要用户登录情况下才可以进行访问的页面或者数据,比如:个人信息功能上。下面的是基于标准版的Authorization中,并使用Bearer开头。可以根据自己的业务需求进行做出更改

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
	return func(c *gin.Context) {
		// 这里根据自己的业务进行更改
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			controller.ResponseError(c, controller.CodeNeedLogin)
			c.Abort()
			return
		}
		// 按空格分割(基于Bearer开头的),如果不是Bearer开头的下面代码可以进行省略
		// ------ start ------
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			controller.ResponseError(c, controller.CodeInvalidToken)
			c.Abort()
			return
		}
		// ------ end -------
		// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
		mc, err := jwt.ParseToken(parts[1])
		if err != nil {
			controller.ResponseError(c, controller.CodeInvalidToken)
			c.Abort()
			return
		}
		// 将当前请求的username信息保存到请求的上下文c上
		c.Set(controller.CtxUserIdKey, mc.UserID)
		c.Next() // 后续的处理函数可以用过c.Get(CtxUserIdKey)来获取当前请求的用户信息
	}
}

中间件引入到路由中

r.POST("/ping", JWTAuthMiddleware(), func(c *gin.Context) {
		c.String(http.StatusOK, "ok!")
	})

到此这篇关于Go语言中JWT的创建和解析操作详解的文章就介绍到这了,更多相关Go JWT的创建和解析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go mod tidy命令的使用

    go mod tidy命令的使用

    gomodtidy命令是Go语言中用于管理项目依赖的工具,主要功能包括移除未使用的依赖项、添加缺失的依赖项以及更新go.sum文件以确保依赖项的正确校验,感兴趣的可以了解一下
    2024-11-11
  • golang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • golang sync.Pool 指针数据覆盖问题解决

    golang sync.Pool 指针数据覆盖问题解决

    本文主要介绍了使用sync.Pool时遇到指针数据覆盖的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • Go 使用Unmarshal将json赋给struct出错的原因及解决

    Go 使用Unmarshal将json赋给struct出错的原因及解决

    这篇文章主要介绍了Go 使用Unmarshal将json赋给struct出错的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Go 切片copy()函数的用法与原理详解

    Go 切片copy()函数的用法与原理详解

    本文详细剖析Go语言切片复制的核心API copy()函数,涵盖基础用法、目标切片长度、复制子切片、目标切片为空、合并切片、与append对比及实战应用,通过具体示例,解释了完全独立复制、不自动扩容、返回值含义等关键知识点
    2026-05-05
  • Go语言基础数组用法及示例详解

    Go语言基础数组用法及示例详解

    这篇文章主要为大家介绍了Go语言基础Go语言数组的用法及示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • Go 语言入门之net/url 包

    Go 语言入门之net/url 包

    这篇文章主要介绍了Go 语言入门之net/url 包,文章基于GO语言的相关资料展开 net/url 包的详细内容,具有一定的的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • Golang结合chromedp实现浏览器自动化操作

    Golang结合chromedp实现浏览器自动化操作

    当大家提到浏览器自动化,第一反应往往是 Python + Selenium, 但其实 Go 语言也能做浏览器自动化,下面我们就来看看Golang如何结合chromedp实现自动化操作网页吧
    2025-12-12
  • Go模板template用法详解

    Go模板template用法详解

    这篇文章主要介绍了Go标准库template模板用法详解;包括GO模板注释,作用域,语法,函数等知识,需要的朋友可以参考下
    2022-04-04
  • Golang并发绕不开的重要组件之Channel详解

    Golang并发绕不开的重要组件之Channel详解

    Channel是一个提供可接收和发送特定类型值的用于并发函数通信的数据类型,也是Golang并发绕不开的重要组件之一,本文就来和大家深入聊聊Channel的相关知识吧
    2023-06-06

最新评论