(基礎)golang+jwt實現用戶登錄獲取token

(基礎)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))
    

    碼字不易,還望各位哥哥姐姐們關注點贊支持一下

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容