Go语言中JWT的创建和解析操作详解
作者:三杯温开水 发布时间:2024-05-09 10:09:22
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
猜你喜欢
- #当前文件的路径pwd = os.getcwd()#当前文件的父路径father_path=os.path.abspath(os.path.
- 如下所示:# -*- coding: utf-8 -*-import numpy as npfrom PyQt5.QtCore import
- 当我们用javascript写ajax程序写得很“开心”的时候,突然有人告诉你有一种东西叫jquery,它会告诉你不直接和HttpReque
- 最近火热全文的ChatGPT,被很多人玩出了花,我们在Github上可以看到几个常见的逆向SDK包,这一篇我将以学习的方式来写这一篇文章。这
- 有好一段时间没有学习新东西了,过了个十月一感觉事情还是越早做越好,废话不多说了,说一下用mybatis连接MySQL数据库,上一篇写了jdb
- 本文实例讲述了原生JS实现Ajax通过POST方式与PHP进行交互的方法。分享给大家供大家参考,具体如下:一、代码conn.php<?
- 一、框架菜单1.1 common模块1.2 其他二、Excel接口测试案例编写三、读取Excel测试封装(核心封装)excel_utils.
- Python3 使用pillow库生成随机验证码的代码如下所示:import random# pillow 包的使用from PIL imp
- 生活中我们为了保障房间里物品的安全,所以给门进行上锁,在我们需要进入房间的时候又会重新打开。同样的之间我们讲过多线程中的lock,作用是为了
- 我们可能会出现这种情况,某个表原来设计不周全,导致表里面的数据数据重复,那么,如何对重复的数据进行删除呢?重复的数据可能有这样两种情况,第一
- 一、原理1.图片必须具有经纬度信息2.经纬度格式转换2.1 GPS点坐标的两种表示方式(误差还是有的)2.1.1 十进制换度分秒例:经纬度1
- 使用socket中的struck来实现客户端发送服务端:客户端:# -*- coding: UTF-8 -*-import socket,
- 这个可能是容易被忽略的问题,首选我们要清楚:MySQL中,AND的执行优先级高于OR。也就是说,在没有小括号()的限制下,总是优先执行AND
- 整理了一下python 中文件的输入输出及主要介绍一些os模块中对文件系统的操作。文件输入输出1、内建函数open(file_name,文件
- 本文实例讲述了python实现合并两个数组的方法。分享给大家供大家参考。具体如下:python合并两个数组,将两个数组连接成一个数组,例如,
- 逻辑回归模型 逻辑回归是应用非常广泛的一个分类机器学习算法,它将数据拟合到一个logit函数(或者叫做logistic函数)中,从而能够完成
- flask是我学习的第一个python的web框架,在应用flask写完一个应用后,当然是把它部署到我们的服务器上了。首先,准备我们部署项目
- 前言前面我们已经介绍了 python面向对象入门教程之从代码复用开始(一) ,这篇文章主要介绍的是关于Python面向对象之设置对
- Reference:https://www.tensorflow.org/install/migrationtensorflow 更新到1.
- 学习使用存储过程(Stored Procedure),是ASP程序员的必须课之一。所有的大型数据库都支持存储过程,比如Oracle