跳到主要内容

JWT

JWT 介绍 JWT 即 JSON Web Token,是用 JSON 形式安全传输信息的方法。

我们可以在 jwt.io 上在线解析 token,可以清楚看懂 JWT 的数据结构。

对 JWT 解码,可以得到以下内容:

Header:TOKEN 的类型,就是JWT,签名的算法,如 HMAC、 SHA256 Payload:携带的信息,比如用户名、过期时间等,一般叫做 Claim Signature:签名,是由header、payload 和你自己维护的一个 secret 经过加密得来的。 JWT 可以设置过期时间,它的应用主要有:

Access Token:添加到 HTTP 请求的 header 中,进行用户认证。加上过期时间可以让 token 被恶意截获后,黑客只有短暂的时间攻击。

Refresh Token:用来给客户端申请新的 Access Token 或者 Refresh Token。比 Access Token 有更长过期时间。

一般服务端生成 JWT 并返回给客户端时,要放在 cookie里,并且加上 HttpOnly 的标记,意味着这个 cookie不能被 JS获取,这样可以防止 XSS 攻击。

Go语言中 JWT 的生成、验证 使用 jwt-go 库生成 JWT。

import github.com/dgrijalva/jwt-go

func CreateToken(uid, secret string) (string, error) {
at := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"uid": uid,
"exp": time.Now().Add(time.Minute * 15).Unix(),
})
token, err := at.SignedString([]byte(secret))
if err != nil {
return "", err
}
return token, nil
}

通常客户端传输 JWT 是通过 header 中的 Authorization 字段,好处是避免了 CORS攻击。并且使用 Bearer 模式。也就是:

Authorization: Bear eyJhbGciO... 在 grpc 中,可以将 JWT 放在 metadata 中:

ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("authorization", "Bearer "+token)) res, _ := client.Call(ctx, ..) 在服务端的验证:

// 忽略 ok为假的情况 incomingContext, ok := metadata.FromIncomingContext(ctx) value, ok := incomingContext["authorization"] uid, err := ParseToken(value[0]) 解析也需要用 jwt-go 库的函数。

// token: "eyJhbGciO..."
func ParseToken(token string, secret string) (string, error) {
claim, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
return "", err
}
return claim.Claims.(jwt.MapClaims)["uid"].(string)
}