网络编程
位置:首页>> 网络编程>> Go语言>> Go语言中JWT的创建和解析操作详解

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

作者:三杯温开水  发布时间:2024-05-09 10:09:22 

标签: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!")
})

来源:https://blog.csdn.net/weixin_47024018/article/details/128304655

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com