golang-jwt的使用

1,124 阅读2分钟

jwt是一个标准的东西,是一个经过加密的字符串。主要用来做web鉴权使用,当然也可以用在所有需要对信息加密的场景。

jwt结构

jwt三部分组成:标头、有效载荷、签名。

1 标头主要有两个数据,说明加密算法和令牌类型

{ "alg": "HS256", "typ": "JWT" }

2 有效载荷分三种类型:注册声明、公共声明、私人声明。

注册声明主要有7个如下

iss:发行人 
exp:到期时间 
sub:主题 
aud:用户 
nbf:在此之前不可用 
iat:发布时间 
jti:JWT ID用于标识该JWT

注册声明并不强制要求有,但是有几个很重要,exp到期时间参数在golang-jwt中会根据该参数自动过期。

1 jwt的生成

golang-jwt是go语言最常用的一个jwt包。

import(
    "github.com/golang-jwt/jwt/v4"
    "github.com/golang-jwt/jwt/v4/request"
)

//第一种方式
func GetToken(secretKey string, iat, seconds, uid int64) (string, error) {
	claims := make(jwt.MapClaims)  //数据仓声明
	claims["exp"] = iat + seconds
	claims["iat"] = iat
	claims["uid"] = uid
	token := jwt.New(jwt.SigningMethodHS256) //token对象
	token.Claims = claims  //token添加数据仓
	return token.SignedString([]byte(secretKey))
}
//第二种方式
func GetToken2(secretKey string, iat, seconds, uid int64) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{"exp": iat+seconds, "uid": 123.1, "iat": iat,"uid":uid})
	tokenstr, error := token.SignedString(secretKey)
	return tokenstr, error
}

jwt.MapClaims 本质就是一个 map[string]interface{},jwt中加载的所有数据都通过MapClaims进行设置。

这里边最终要的就是exp 有了这个参数解析时候才能验证token串是否有效

2 jwt加密串的解析

//第一种
tk, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
    return []byte(secretKey), nil
})
if tk.Valid{
    for k,v:=range tk.Claims.(jwt.MapClaims){
        fmt.Println(k,":",v)
    }
}

jwt.Parse解析后返回一个token对象,token对象里有个Valid属性,标识该token串是否有效,除了验证token串的加密有效性还会验证exp是否过期。token对象的Claims属性是个接口,可以转城jwt.MapClaims,从而拿到token中的附载数据。

//第二种
r := map[string]interface{}{
    "exp": time.Now().Unix(),
}
tk, err := jwt.ParseWithClaims(token, jwt.MapClaims(r), func(t *jwt.Token) (interface{}, error) {
    return []byte(sec), nil
})

jwt.ParseWithClaims多了一个默认jwt.MapClaims参数,该参数值中的数据都是默认值,当token串中无对应数据则会用默认值,建议添加默认exp参数值。

3 request中jwt解析

jwt经常会用在web中,在golang-jwt库中,也有个专门的request包来进行处理。

import(
    "github.com/golang-jwt/jwt/v4"
    "github.com/golang-jwt/jwt/v4/request"
)
        sec:="abc"
        now:=time.Now().Unix()
        token,_:=GetToken(abc,now+30,now,1)
	r := httptest.NewRequest(http.MethodGet, "http://www.abc.com", nil)
	r.Header.Add("Authorization", token)
	tk, err := request.ParseFromRequest(r, request.AuthorizationHeaderExtractor, func(t *jwt.Token) (interface{}, error) {
		return []byte(sec), nil
	})
        

request.ParseFromRequest中的第二个参数是一个提取器,类型为request.Extractor,这是一个接口,原型如下:

type Extractor interface {
	ExtractToken(*http.Request) (string, error)
}

request.AuthorizationHeaderExtractor 实现了该接口,使用"Authorization" 对token进行提取。