日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

Go語(yǔ)言如何使用golang-jwt/jwt/v4進(jìn)行JWT鑒權(quán)詳解_Golang

作者:楓花海 ? 更新時(shí)間: 2022-11-09 編程語(yǔ)言

前言

最近寫的項(xiàng)目中用到了JWT鑒權(quán),因此做個(gè)記錄

原先的jwt-go倉(cāng)庫(kù)已經(jīng)不再維護(hù),遷移到了github.com/golang-jwt/jwt/v4

但是網(wǎng)上大多數(shù)還是v3版本的使用教程,建議使用更加安全的v4

1.什么是JWT

JSON Web Token (JWT)是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對(duì)象在各方之間安全地傳輸信息。特別適用于分布式站點(diǎn)的單點(diǎn)登錄(SSO)場(chǎng)景。JWT的聲明一般被用來(lái)在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該token也可直接被用于認(rèn)證,也可被加密。

2.JWT的數(shù)據(jù)結(jié)構(gòu)

實(shí)際的JWT由三部分組成,如下圖

中間用點(diǎn)(.)分隔成三個(gè)部分。注意,JWT 內(nèi)部是沒(méi)有換行的,這里只是為了便于展示,將它寫成了幾行。JWT的三個(gè)部分依次如下:

  • Header(頭部)
  • Payload(負(fù)載)
  • Signature(簽名)

寫成一行就是Header.Payload.Signature

2.1 Header

Header 部分是一個(gè) JSON 對(duì)象,描述 JWT 的元數(shù)據(jù),通常是下面的樣子

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

上面代碼中,alg屬性表示簽名的算法(algorithm),默認(rèn)是HMAC SHA256(寫成 HS256);typ屬性表示這個(gè)令牌(token)的類型(type),JWT 令牌統(tǒng)一寫為JWT

將上面的 JSON 對(duì)象使用 Base64URL 算法(詳見(jiàn)后文)轉(zhuǎn)成字符串就成了第一部分Header

2.2 Payload

Payload 部分也是一個(gè) JSON 對(duì)象,用來(lái)存放實(shí)際需要傳遞的數(shù)據(jù)。JWT 規(guī)定了7個(gè)官方字段,供選用。

  • iss (issuer):簽發(fā)人
  • exp (expiration time):過(guò)期時(shí)間
  • sub (subject):主題
  • aud (audience):受眾
  • nbf (Not Before):生效時(shí)間
  • iat (Issued At):簽發(fā)時(shí)間
  • jti (JWT ID):編號(hào)

我們還可以在這個(gè)部分自己定義字段,下面就是一個(gè)例子

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

注意,JWT 默認(rèn)是不加密的,任何人都可以讀到,所以不要把秘密信息放在這個(gè)部分。

這個(gè) JSON 對(duì)象也要使用 Base64URL 算法轉(zhuǎn)成字符串。

2.3 Signature

Signature 部分是對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。

首先,需要指定一個(gè)密鑰(secret)。這個(gè)密鑰只有服務(wù)器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認(rèn)是 HMAC SHA256),按照下面的公式產(chǎn)生簽名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

2.4 Base64URL

前面提到,HeaderPayload 串型化的算法是 Base64URL。這個(gè)算法跟 Base64 算法基本類似,但有一些小的不同。

JWT 作為一個(gè)令牌(token),有些場(chǎng)合可能會(huì)放到 URL(比如 api.example.com/?token=xxx)。Base64 有三個(gè)字符+,/和=,在 URL 里面有特殊含義,所以要被替換掉:=被省略、+替換成-,/替換成_ 。這就是 Base64URL 算法。

算出簽名以后,把 HeaderPayloadSignature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)"(.)分隔,就可以返回給用戶。

3使用JWT

安裝

go install "github.com/golang-jwt/jwt/v4"

生成Token

定義claimsserect

type MyClaims struct {
	Phone string `json:"phone"`
	jwt.RegisteredClaims  // 注意!這是jwt-go的v4版本新增的,原先是jwt.StandardClaims
}

var MySecret = []byte("手寫的從前") // 定義secret,后面會(huì)用到

生成token

// 這里傳入的是手機(jī)號(hào),因?yàn)槲翼?xiàng)目登陸用的是手機(jī)號(hào)和密碼
func MakeToken(phone string) (tokenString string, err error) {
	claim := MyClaims{
		Phone: phone,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Hour * time.Duration(1))), // 過(guò)期時(shí)間3小時(shí)
			IssuedAt:  jwt.NewNumericDate(time.Now()),     // 簽發(fā)時(shí)間
			NotBefore: jwt.NewNumericDate(time.Now()),     // 生效時(shí)間
		}}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim) // 使用HS256算法
	tokenString, err = token.SignedString(MySecret)
	return tokenString, err
}

解析token

func Secret() jwt.Keyfunc {
	return func(token *jwt.Token) (interface{}, error) {
		return []byte("手寫的從前"), nil  // 這是我的secret
	}
}

func ParseToken(tokenss string) (*MyClaims, error) {
	token, err := jwt.ParseWithClaims(tokenss, &MyClaims{}, Secret())
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, errors.New("that's not even a token")
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, errors.New("token is expired")
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, errors.New("token not active yet")
			} else {
				return nil, errors.New("couldn't handle this token")
			}
		}
	}
	if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New("couldn't handle this token")
}

參考:

JSON Web Token 入門教程

總結(jié)

原文鏈接:https://blog.csdn.net/weixin_44294408/article/details/122095919

欄目分類
最近更新