JWT 是 Json Web Token 的縮寫,是一個簽名的Json對象,能夠用做身份驗證。Bearer
在Oauth2中一般用於令牌。令牌由三部分組成,以 .
分割。前兩部分是JSON對象,並進行base64url
編碼,最後一部分是簽名,以相同格式編碼。javascript
JWT原理:在服務器認證後,生成一個加密的 JSON 對象,即 Token 返還給用戶,以後用戶與服務端通訊都須要帶上該 Token 令牌,服務器只依靠該令牌認定用戶身份是否合法,所以服務器就不須要保存任何 session 數據了。 每當用戶想要訪問受保護的路由或資源時,用戶代理應該使用承載模式發送JWT,一般在Authorization Header
中。Header的內容應以下所示:java
Authorization: Bearer <token>
複製代碼
JWT的組成:Header.Payload.Signature
git
{
"alg":"HS256",
"typ":"JWT"
}
複製代碼
alg
屬性表示簽名的算法爲 HS256(HMAC SHA256),typ
屬性表示該 Token 的類型,JWT令牌統一寫爲 JWT
。最後將該對象經過 Base64URL
算法轉爲字符串github
{
"userId":"123"
"exp":"3132134213"
"iat":"1231312323"
}
複製代碼
能夠在該對象中添加時間戳屬性,iat
屬性用來表示當前時間戳,exp
屬性表示到期時間戳,有了這兩個屬性就能夠驗證 token 是否過時。該對象也要通過 Base64Url
編碼算法
secret
密鑰,這個密鑰只有服務器知道,而後使用 Header 中指定的簽名算法 生成簽名,如下爲 HMAC SHA256 算法建立簽名:HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
複製代碼
官方地址: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 屬性,以後能夠進行其餘操做