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)
}
我的博客即將同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=2qjttvtxcaqsw
我的博客即將同步至 OSCHINA 社區,這是我的 OSCHINA ID:饒文津,邀請大家一同入駐:https://www.oschina.net/sharing-plan/apply