在 GoLang 中使用 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)
}

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM