(基礎)golang+jwt實現用戶登錄獲取token
-
1.根據用戶名/密碼獲取token Service
JWT(JSON Web Token)
是一個非常輕巧的規范。這個規范允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。一個JWT由三部分組成,<font color='red'>頭部、載荷 與 簽名</font>。
JWT原理類似我們加蓋公章或手寫簽名的的過程,合同上寫了很多條款,不是隨便一張紙隨便寫啥都可以的,必須要一些證明,比如簽名,比如蓋章。JWT就是通過附加簽名,保證傳輸過來的信息是真的,而不是偽造的;
載荷:
包含生成Token時間,過期時間,以及一些身份標識,標準定義了6個字段,載荷json經過base64編碼后得到JWT的載荷:
Payload載荷: jti:該jwt的唯一標識 iss:該jwt的簽發者 iat:該jwt的簽發時間 aud:該jwt的接收者 sub:該jwt的面向的用戶 nbf:該jwt的生效時間,可不設置,若設置,一定要大于當前Unix UTC,否則token將會延遲生效 exp:該jwt的過期時間 可自定義其他key-value形式的數據作為載體
簽名:
將頭部和載荷用'.'號連接,再加上一串密鑰,經過頭部聲明的加密算法加密后得到簽名
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
JWT Token
Token=頭部+'.'+載荷+'.'+簽名
基本數據結構
上面是簽名的使用例子,下面分析簽名的源碼實現,首先看下數據結構Token,包含了我們標準中說道的三部分:頭部,載荷和簽名,此外還帶了一個用于存儲生成token的字段Raw和校驗標識符Valid
// A JWT Token. Different fields will be used depending on whether you're // creating or parsing/verifying a token. type Token struct { Raw string // The raw token. Populated when you Parse a token Method SigningMethod // The signing method used or to be used Header map[string]interface{} // The first segment of the token Claims Claims // The second segment of the token Signature string // The third segment of the token. Populated when you Parse a token Valid bool // Is the token valid? Populated when you Parse/Verify a token }
==定義密鑰==
var tokenApiSecretKey="itxjTokenApi980420"
獲取token
//get token
func GetTokenService(name string,pwd string)(string,error){
//非空校驗
if common.IsEmpty(name) || common.IsEmpty(pwd) {
return "",errors.New("賬號,密碼不能為空")
}
token := jwt.New(jwt.SigningMethodHS256)
claims:=make(jwt.MapClaims)
claims["jti"]=time.Now().Unix()
claims["iss"]="itxj"
claims["iat"]=time.Now()
claims["aud"]="mam"
claims["sub"]=name
claims["nbf"]=time.Now().Unix()
claims["exp"]=time.Now().Add(time.Hour*time.Duration(24)).Unix()
claims["cs"]="this is cs claims"
token.Claims=claims
tokenStr, err := token.SignedString([]byte(tokenApiSecretKey))
if err!=nil {
return "",err
}
return tokenStr,nil
}
校驗token
//校驗token
func ValidateTokenService(tokenStr string)(bool,error){
token, errByParseToken := jwt.Parse(tokenStr, func(token *jwt.Token) (i interface{}, e error) {
return []byte(tokenApiSecretKey),nil
})
if errByParseToken!=nil {
return false,errors.New("An invalid Token ")
}
if !token.Valid {
return false,errors.New("fail while invalid Token ")
}
return true,nil
}
> 獲取校驗成功后的token(*jwt.Token)
>
>
//獲取校驗并且返回token
func GetValidateTokenService(tokenStr string)(*jwt.Token,error){
token, er := jwt.Parse(tokenStr, func(token *jwt.Token) (i interface{}, e error) {
return []byte(tokenApiSecretKey), nil
})
if er!=nil {
return token,er
}
return token,nil
}
校驗成功后根據key獲取token中載荷的數據
//從token claims中提取數據
func GetValFormTokenClaims(key string,claims jwt.Claims)string{
v := reflect.ValueOf(claims)
if v.Kind() == reflect.Map {
for _, k := range v.MapKeys() {
value := v.MapIndex(k)
if fmt.Sprintf("%s", k.Interface()) == key {
return fmt.Sprintf("%v", value.Interface())
}
}
}
return ""
}
-
2.測試
//獲取token tokenStr, errByGetToken := service.GetTokenService("itxj", "itxj") if errByGetToken!=nil { fmt.Printf("Get Token error......%s",errByGetToken.Error()) return } fmt.Printf("token=%s\n",tokenStr) //校驗token isValidate, errByParseToken := service.ValidateTokenService(tokenStr) if errByParseToken!=nil { fmt.Printf("Validate Token error......%s",errByParseToken.Error()) return } fmt.Printf("token is =%v\n",isValidate) //獲取校驗成功的token token, errByGetParseToken := service.GetValidateTokenService(tokenStr) if errByGetParseToken!=nil{ fmt.Printf("Get Validate Token error......%s",errByGetParseToken.Error()) return } claims := token.Claims fmt.Printf("token.sub=%s;\n",service.GetValFormTokenClaims("sub",claims)) fmt.Printf("token.cs=%s;\n",service.GetValFormTokenClaims("cs",claims))
碼字不易,還望各位哥哥姐姐們關注點贊支持一下