目录获取Token解析Token实际使用测试结果结语
JWT(JSON Web Token)是一种基于JSON的安全令牌,可以用于在不同系统之间传输认证信息。在Go中实现JWT验证,可以通过标准库、和来编写自己的JWT。
我们在此封装一个JWT的struct结构体(由于除了Payload,其他很大可能不会在其他地方用到,所以不公开)
type JWT struct {
header string
Payload string
signature string
}
header string
Payload string
signature string
}
将base64的编码封装一下方便使用
func encodeBase64(data string) string {
return base64.RawURLEncoding.EncodeToString([]byte(data))
}
return base64.RawURLEncoding.EncodeToString([]byte(data))
}
我们封装一个用来生成签名的方法
func generateSignature(key []byte, data []byte) (string, error) {
// 创建一个哈希对象
hash :=hmac.New(sha256.New, key)
// 将要签名的信息写入哈希对象中 hash.Write(data)
_, err :=hash.Write(data)
if err !=nil {
return “”, err
}
// hash.Sum()计算签名,在这里会返回签名内容
// 将签名经过base64编码生成字符串形式返回。
return encodeBase64(string(hash.Sum(nil))), nil
}
// 创建一个哈希对象
hash :=hmac.New(sha256.New, key)
// 将要签名的信息写入哈希对象中 hash.Write(data)
_, err :=hash.Write(data)
if err !=nil {
return “”, err
}
// hash.Sum()计算签名,在这里会返回签名内容
// 将签名经过base64编码生成字符串形式返回。
return encodeBase64(string(hash.Sum(nil))), nil
}
我们封装一个CreateToken用于生成Token(该方法的参数key为(生成签名所使用的密钥))
func CreateToken(key []byte, payloadData any) (string, error) {
// 标准头部
header :=`
// 标准头部
header :=`
我们封装一个解析token的方法
func ParseJwt(token string, key []byte) (*JWT, error) {
// 分解规定,我们使用.进行分隔,所以我们通过.进行分隔成三个字符串的数组
jwtParts :=strings.Split(token, “.”)
// 数据数组长度不是3就说明token在格式上就不合法
if len(jwtParts) !=3 {
return nil, fmt.Errorf(“非法token”)
}
// 分别拿出
encodedHeader :=jwtParts[0]
encodedPayload :=jwtParts[1]
signature :=jwtParts[2]
// 使用key将token中的头部和负载用.连接后进行签名
// 这个签名应该个token中第三部分的签名一致
confirmSignature, err :=generateSignature(key, []byte(encodedHeader+”.”+encodedPayload))
if err !=nil {
return nil, fmt.Errorf(“生成签名错误”)
}
// 如果不一致
if signature !=confirmSignature {
return nil, fmt.Errorf(“token验证失败”)
}
// 将payload解base64编码
dstPayload, _ :=base64.RawURLEncoding.DecodeString(encodedPayload)
// 返回我们的JWT对象以供后续使用
return &JWT{encodedHeader, string(dstPayload), signature}, nil
}
// 分解规定,我们使用.进行分隔,所以我们通过.进行分隔成三个字符串的数组
jwtParts :=strings.Split(token, “.”)
// 数据数组长度不是3就说明token在格式上就不合法
if len(jwtParts) !=3 {
return nil, fmt.Errorf(“非法token”)
}
// 分别拿出
encodedHeader :=jwtParts[0]
encodedPayload :=jwtParts[1]
signature :=jwtParts[2]
// 使用key将token中的头部和负载用.连接后进行签名
// 这个签名应该个token中第三部分的签名一致
confirmSignature, err :=generateSignature(key, []byte(encodedHeader+”.”+encodedPayload))
if err !=nil {
return nil, fmt.Errorf(“生成签名错误”)
}
// 如果不一致
if signature !=confirmSignature {
return nil, fmt.Errorf(“token验证失败”)
}
// 将payload解base64编码
dstPayload, _ :=base64.RawURLEncoding.DecodeString(encodedPayload)
// 返回我们的JWT对象以供后续使用
return &JWT{encodedHeader, string(dstPayload), signature}, nil
}
我们构造一个用户的结构体
type UserInfo struct {
Name string `json:”name”`
Password string `json:”password”`
}
Name string `json:”name”`
Password string `json:”password”`
}
我们这次使用123456作为密钥简单的验证一下
var Key []byte=[]byte(“12346”)
在此我们构造一个验证的中间件
func jwtConfirm(context *gin.Context) {
// 登录不需要token
if context.Request.RequestURI==”/login” {
return
}
// 拿出token
token :=context.GetHeader(“Token”)
// 进行解析验证
jwt, err :=utils.ParseJwt(token, Key)
if err !=nil {
context.JSON(200, gin.H{
“msg”: err.Error(),
})
// 有问题就流产掉(我也不知道怎么翻译好了,香蕉猫.jpg)
context.Abort()
}
// 验证通过就将负载返回回去
context.JSON(200, gin.H{
“payload”: jwt.Payload,
})
}
// 登录不需要token
if context.Request.RequestURI==”/login” {
return
}
// 拿出token
token :=context.GetHeader(“Token”)
// 进行解析验证
jwt, err :=utils.ParseJwt(token, Key)
if err !=nil {
context.JSON(200, gin.H{
“msg”: err.Error(),
})
// 有问题就流产掉(我也不知道怎么翻译好了,香蕉猫.jpg)
context.Abort()
}
// 验证通过就将负载返回回去
context.JSON(200, gin.H{
“payload”: jwt.Payload,
})
}
我们在此基础上就可以使用了,这边使用gin框架简单的测试一下
func main() {
// 使用默认路由
router :=gin.Default()
// 注册中间件
router.Use(jwtConfirm)
// 简单做两个服务
router.POST(“/login”, func(context *gin.Context) {
// 接收用户参数
var userInfo UserInfo=UserInfo{}
// 使用jsonbind接收
bindErr :=context.ShouldBindJSON(&userInfo)
if bindErr !=nil {
context.JSON(200, gin.H{
“msg”: bindErr.Error(),
})
}
// 使用密钥做出token
jwt, err :=utils.CreateJwt(Key, userInfo)
if err !=nil {
fmt.Println(err)
}
// 我们将token直接返回用于测试
context.JSON(200, gin.H{
“token”: jwt,
})
})
router.GET(“/doing”)
router.Run()
}
// 使用默认路由
router :=gin.Default()
// 注册中间件
router.Use(jwtConfirm)
// 简单做两个服务
router.POST(“/login”, func(context *gin.Context) {
// 接收用户参数
var userInfo UserInfo=UserInfo{}
// 使用jsonbind接收
bindErr :=context.ShouldBindJSON(&userInfo)
if bindErr !=nil {
context.JSON(200, gin.H{
“msg”: bindErr.Error(),
})
}
// 使用密钥做出token
jwt, err :=utils.CreateJwt(Key, userInfo)
if err !=nil {
fmt.Println(err)
}
// 我们将token直接返回用于测试
context.JSON(200, gin.H{
“token”: jwt,
})
})
router.GET(“/doing”)
router.Run()
}
我们拿到了token
我们现在去试一下如果不带token的结果
我们试一下携带错误token的情况
我们最后测试一下正确的token
在实际环境中会使用更复杂的情况进行使用(例如密钥会更加复杂,会在pyload中设置失效时间等等),但是生成token和解析token的操作和上述的操作差别不大
到此这篇关于golang原生实现JWT的示例代码的文章就介绍到这了,更多相关golang原生实现JWT内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:golang中的jwt使用教程流程分析Golang使用JWT进行认证和加密的示例详解Golang基于JWT与Casbin身份验证授权实例详解go语言使用jwt认证的实现go语言beego框架jwt身份认证实现示例Go语言中JWT的创建和解析操作详解
© 版权声明
文章版权归作者所有,未经允许请勿转载。