jwt-go库介绍
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jwt-go库介绍相关的知识,希望对你有一定的参考价值。
参考技术A这个库已经没人维护了,他们现在新搞了一个,具体可以去github上看
jwt(json web token)是一种用于前后端身份认证的方法,一个jwt由header,payload,和signature组成。
1.Claims
claims是一个实现了Valid方法的interface,Valid方法用于判断该claim是否合法
2.Keyfunc
Keyfunc在使用时一般都是返回secret密钥,可以根据Token的种类不同返回不同的密钥.
官方文档:This allows you to use properties in the Header of the token (such as \'kid\') to identify which key to use.
3.Mapclaims
一个用于放decode出来的claim的map,有Vaild和一系列VerifyXXX的方法
4.Parser
用来将tokenstr转换成token
5.SigningMethod
签名方法的接口,可以通过实现这个接口自定义签名方法,jwt-go内置一些实现了SigningMethod的结构体
6.StandardClaims
jwt官方规定的一些预定义的payload:
7.Token
Token的结构体
8.ValidationError
定义解析Token时遇到的一些错误
首先我们先来看Parse()
实际上是调用了ParseWithClaims,第二个参数就是一个map[string]interface,这个函数的源码如下,这个函数内部调用的ParseUnverified,我们先来看看这个函数
官方的解释是,这个函数不校验签名的有效性,只单纯负责把tokenStr变成Token对象,而之后的事情就是交给ParseWithClaims来做啦
可以看到,ParseUnverified这个方法真的只是单纯的解码Header段和Claim段,然后检查一下用的alg是不是合法,就返回了,让我们继续往下看验证的逻辑
ok,关于解析token的主要方法我们已经看完了,接下来我们来看看如何生成一个token,其实就是反着操作一遍
先看New函数,选择一种SigningMethod,新建一个token,内部调用NewWithClaims
再看NewWithClaims,发现就是简单的给JwtToken的三个部分赋值
最后是SignedString,即使用alg的算法给token加密,生成最终的tokenStr,内部调用了SigningString,所以先看SigningString
发现SigningString就是把token的头部先变成json然后base64url编码,但是没有生成jwtToken的最后一个部分
所以SignedString作用就是用给定的加密方法和你的SecretKey对前面两部分加密,添在token的最后一段,至此token生成完毕
Go开源宝藏JWT-Go 鉴权 | 中间件 (文末送书嗷~)
- 🎉粉丝福利送书:《Go语言区块链应用开发从入门到精通》
- 🎉点赞 👍 收藏 ⭐留言 📝 即可参与抽奖送书
- 🎉下周三(9月22日)晚上20:00将会在【点赞区和评论区】抽一位粉丝送这本书~🙉
- 🎉详情请看第四点的介绍嗷~✨
本文介绍Go语言的中间件
JWT-Go
鉴权
JSON Web Token (JWT)
是目前最流行的跨域身份验证解决方案
生成token
用于前后端交互中验证用户信息
github.com/dgrijalva/jwt-go
1. JWT是什么
我们知道HTTP是无状态
的,所以说每一次发送HTTP请求的时候,都必须要带点身份验证
的东西,来验证访问者的身份。
传统的做法是将已经认证过的用户信息存储在服务器
上,比如Session
。用户下次请求的时候带着Session ID
,然后服务器以此检查用户是否认证过。
但是这个基于服务器的身份验证
存在很多的问题
-
Sessions : 每次用户认证通过以后,服务器需要创建一条记录保存用户信息,通常是在内存中,随着认证通过的用户越来越多,服务器的在这里的开销就会越来越大。
-
Scalability : 由于Session是在内存中的,这就带来一些扩展性的问题。
-
CORS : 当我们想要扩展我们的应用,让我们的数据被多个移动设备使用时,我们必须考虑跨资源共享问题。当使用AJAX调用从另一个域名下获取资源时,我们可能会遇到禁止请求的问题。
而JWT
的出现很好地解决了这些问题。
JWT是在服务器身份验证之后,生成一个JSON对象并将其发送回用户。
{
"UserName": "FanOne",
"Role": "Admin",
"Expire": "2021-09-21 20:00:00"
}
之后,当用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识
用户。
为了防止用户篡改数据,服务器将在生成对象时添加签名。
服务器不保存任何会话数据,即服务器变为无状态
,使其更容易扩展。
2. JWT的结构
2.1 JWT头
Header
典型的由两部分组成:token
的类型(“JWT”)和算法名称(比如:HMAC SHA256
或者RSA
等等)。
{
"alg": "HS256",
"typ": "JWT"
}
- alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);
- typ属性表示令牌的类型,JWT令牌统一写为JWT。
2.2 有效载荷
Preload
是JWT的主体内容部分,也是一个JSON对象
,包含需要传递的数据。 JWT指定七个默认字段供选择。
Registered claims
: 这里有一组预定义的声明,它们不是强制的,但是推荐
- iss:发行人
- exp:到期时间
- sub:主题
- aud:用户
- nbf:在此之前不可用
- iat:发布时间
- jti:JWT ID用于标识该JWT
Public claims
: 可以随意定义。
Private claims
: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。例如:
{
"sub": '10086',
"name": 'FanOne',
"admin":true
}
2.3签名哈希
签名哈希
是对上面两部分数据进行签名,通过指定的算法生成哈希,以确保数据不会被篡改。
签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。
3. 如何使用JWT-Go
3.1 下载导入
go get github.com/dgrijalva/jwt-go
3.2 使用
- 定义一个
jwtSecret
var jwtSecret = []byte(os.Getenv("JWT_SECRET"))
- 定义一个
Chaims
结构体
我这里是把用户的id,用户的name,open_id,authority放进去了加密了,后续解密出来的话,也是这些信息,然后再用这些信息去匹配。
type Claims struct {
UserID uint `json:"user_id"` // 自定义的
UserName string `json:"user_name"`
OpenID string `json:"open_id"`
Authority int `json:"authority"`
jwt.StandardClaims //官方推荐的
}
- 签发用户Token
//GenerateToken 签发用户Token
func GenerateToken(userid uint,username, open_id string, authority int) (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(24 * time.Hour) // Token过期时间
claims := Claims{
UserID : userid,
UserName: username,
OpenID: open_id,
Authority: authority,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "FanOne",
},
}
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString(jwtSecret)
return token, err // 返回token
}
- 验证用户Token
func ParseToken(token string) (*Claims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if tokenClaims != nil {
if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
return claims, nil
}
}
return nil, err
}
将token
进行解析,然后就能生成对应的Claims
,这个Claims
就有上文你放进入的信息。
3.3 例子
Gin框架作为例子
- 在
路由初始化
的时候,在路由上添加中间件,这样加进去就能验证身份了。
r.Use(middleware.JWT())
- 在
package middleware
中,我们可以定义这个middleware
,这样就能在执行下面路由的时候,验证这个token是否符合要求了。
func JWT() gin.HandlerFunc {
return func(c *gin.Context) {
var code int
var data interface{}
code = 200
token := c.GetHeader("Authorization")
if token == "" {
code = 404
} else {
claims, err := util.ParseToken(token)
if err != nil {
code = e.ErrorAuthCheckTokenFail
} else if time.Now().Unix() > claims.ExpiresAt {
code = e.ErrorAuthCheckTokenTimeout
}
}
if code != e.Success {
c.JSON(200, gin.H{
"status": code,
"msg": e.GetMsg(code),
"data": data,
})
c.Abort()
return
}
c.Next()
}
}
4. 福利送书
点赞
、评论
即可参与评论区的送书活动
,抽一位小伙伴送书~
【编辑推荐】
- 理论与实践相结合,每个理论都有对应的实践代码讲解,读者参考源码,完成实例,就可以
看到实践效果。 - 每章都配备实训与问答。读者阅读后,能尽快巩固知识点,可以做到举一反三、学以致用。
- 内容知识体系系统、完备,可以快速帮助读者搭建区块链应用开发知识体系。
- 易学易懂,零基础读者只要能够理解一些编程上的关键术语就可以阅读本书。Go语言和Solidity是两门独立的开发语言,在本书中都进行了较为细致的讲解,便于读者由浅入深地学习。
【内容简介】
《GO语言区块链应用开发从入门到精通》全面地介绍了Go语言区块链应用工程师所需要的基础知识和各种技术,主要分为
基础篇
、进阶篇
和实战篇
三部分。
全书共7章
- 其中1~2章为
基础篇
,介绍Go语言环境安装、基础语法、函数编程、容器编程、面向对象编程、并发编程以及网络编程; - 3~5章为
进阶篇
: - 第3章介绍区块链基本原理、发展历程、行业应用案例
- 第4章主要介绍
智能合约
,包括solidity基础语法,多个经典案例,以及Go语言如何调用智能合约 - 第5章主要介绍区块链原理的
程序化实践
,包括Go语言实现Base58编码、P2P网络、PoW共识、区块链组块以及UTXO账户模型实现; - 6~7章为
实战篇
,介绍2个实战项目: - 第6章介绍如何实现Go语言版的
区块链钱包项目
,内容包括助记词生成、私钥存储、Coin交易以及Token交易等内容 - 第7章介绍如何实现一个
版权交易系统
,内容包含如何去设计区块链应用系统、后端功能如何与区块链相结合,它既是一个区块链系统应用项目,也是一个Go语言Web服务器项目。
《GO语言区块链应用开发从入门到精通》适合想从事GO语言区块链开发的程序员及GO语言爱好者阅读。
没有中奖的同学可以到这些平台去`康康`嗷~
京东:https://item.jd.com/12858507.html
当当:http://product.dangdang.com/29246989.html
最后
小生凡一,期待你的关注。
以上是关于jwt-go库介绍的主要内容,如果未能解决你的问题,请参考以下文章