Go Iris 中使用 JWT

JWT簡介

JWTJson Web Token 的縮寫,是一個簽名的Json對象,能夠用做身份驗證。Bearer 在Oauth2中一般用於令牌。令牌由三部分組成,以 . 分割。前兩部分是JSON對象,並進行base64url編碼,最後一部分是簽名,以相同格式編碼。javascript

JWT原理:在服務器認證後,生成一個加密的 JSON 對象,即 Token 返還給用戶,以後用戶與服務端通訊都須要帶上該 Token 令牌,服務器只依靠該令牌認定用戶身份是否合法,所以服務器就不須要保存任何 session 數據了。 每當用戶想要訪問受保護的路由或資源時,用戶代理應該使用承載模式發送JWT,一般在Authorization Header中。Header的內容應以下所示:java

Authorization: Bearer <token>
複製代碼

JWT的組成:Header.Payload.Signaturegit

  • Header(頭部):一個JSON對象,描述JWT的元數據,通常以下:
{
    "alg":"HS256",
    "typ":"JWT"
}
複製代碼

alg屬性表示簽名的算法爲 HS256(HMAC SHA256),typ屬性表示該 Token 的類型,JWT令牌統一寫爲 JWT。最後將該對象經過 Base64URL 算法轉爲字符串github

  • Payload(負載):也是JSON對象,用來存放實際須要傳遞的數據
{
    "userId":"123"
    "exp":"3132134213"
    "iat":"1231312323"
}
複製代碼

能夠在該對象中添加時間戳屬性,iat屬性用來表示當前時間戳,exp屬性表示到期時間戳,有了這兩個屬性就能夠驗證 token 是否過時。該對象也要通過 Base64Url編碼算法

  • Signature(簽名):因爲前兩部分雖然通過編碼,數據不可串改,可是是透明的,爲了防止數據被惡意篡改,須要對前兩部分簽名。首先須要定義一個 secret密鑰,這個密鑰只有服務器知道,而後使用 Header 中指定的簽名算法 生成簽名,如下爲 HMAC SHA256 算法建立簽名:
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
複製代碼

在Iris中使用 JWT

官方地址:github.com/dgrijalva/j…bash

終端下載:服務器

// 使用 go mod 的話直接在項目中 go get
go get "github.com/dgrijalva/jwt-go" 
複製代碼

自定義 JWT 中間件驗證:session

import (
	"github.com/dgrijalva/jwt-go"
	jailer "github.com/iris-contrib/middleware/jwt"
)

/** * 驗證 jwt * @method JwtHandler */
func JwtHandler() *jailer.Middleware {
	return jailer.New(jailer.Config{
		// 驗證 jwt 的 token 的方法
		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
			// 本身加密的密鑰
			return []byte("secret"), nil
		},

		SigningMethod: jwt.SigningMethodHS256,
		Expiration:true,
	})

}
複製代碼

這樣一個簡單的驗證 token 的中間件就寫好了。讓咱們看一下中間件的配置 jailer.Config JWT 中 結構體 Config 源碼解析函數

type Config struct {
	//返回 JWT 驗證簽名 密鑰的函數,默認值爲nil
	ValidationKeyGetter jwt.Keyfunc
	// 請求中用戶(&令牌)信息所在的屬性的名稱,若是是 JWT 將會被存儲,默認值爲 jwt
	ContextKey string
	// 令牌驗證出錯調用的函數
	ErrorHandler errorHandler
	// 是否須要憑證,默認值 false
	CredentialsOptional bool
	//從 request 中提取 token 的函數 默認 FromAuthHeader 從 from Authorization header 中獲取 token
	Extractor TokenExtractor
	// 設置後,全部使用OPTIONS方法的請求都將使用身份驗證
	//若是使用需在 路由中註冊,默認值爲 false
	EnableAuthOnOptions bool
	// 設置以後,middelware將驗證是否使用特定的簽名算法對令牌進行了簽名,若是簽名方法不是常量,可使用ValidationKeyGetter回調來實現其餘檢查,默認值 nil
	SigningMethod jwt.SigningMethod
	// 驗證 令牌是否過時,若是過時返回 過時錯誤,默認值 false
	Expiration bool
}
複製代碼

在登錄的時候生成 JWT Tokenui

token := jwt.New(jwt.SigningMethodHS256) // 建立 Header ,算法爲 HS256
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Add(time.Hour * time.Duration(12)).Unix()// 時間戳
claims["iat"] = time.Now().Unix() // 生成時的當前時間戳
claims["user_id"] = user.Id // 自定義屬性
token.Claims = claims
tokenString, err := token.SignedString([]byte("secret")) // 簽名密鑰
複製代碼

tokenString 就是咱們獲得的 Token 令牌了,在令牌中的第二部分加入了 user_id屬性,方便以後用戶在登錄時候的其餘操做

在路由中添加 中間件驗證

v1.PartyFunc("/login", func(login router.Party) {
    login.Post("/user_login", controller.Login)
    login.Post("/user_reg", controller.Register)
})
v1.Use(middleware.JwtHandler().Serve)
複製代碼

JWT 自帶驗證方法,若是想再自行加入驗證能夠註冊新的中間件,例如

// 路由驗證
v1.Use(middleware.JwtHandler().Serve, middleware.AuthToken)

// middleware.AuthToken 中間件 中部分代碼
func AuthToken(ctx iris.Context) {
    u := ctx.Values().Get("jwt").(*jwt.Token) //獲取 token 信息
    userId, _ := u.Claims.(jwt.MapClaims)["user_id"]
}
複製代碼

如例子,能夠獲取到咱們以前 存在token中的 userId 屬性,以後能夠進行其餘操做

相關文章
相關標籤/搜索