首页 > golang > golang与-Laravel框架的 tymon/jwt-auth jwt互通
2024
02-20

golang与-Laravel框架的 tymon/jwt-auth jwt互通

废话不多说,直接上代码

package main

import (
   "errors"
   "fmt"
   "github.com/dgrijalva/jwt-go"
   "log"
   "time"
)

// 一些常量
var (
   TokenExpired     error  = errors.New("Token is expired")
   TokenNotValidYet error  = errors.New("Token not active yet")
   TokenMalformed   error  = errors.New("That's not even a token")
   TokenInvalid     error  = errors.New("Couldn't handle this token:")
   SignKey          string = "newtrekWang"
   hmacSampleSecret string = "xTcDKckjG37IrfRoCs35uEc13mF%vuNYlBM%gLznpVmN6yoEEj1H6F9wpjBfmq7k"
)

type JWT struct {
   SigningKey []byte
}

type CustomClaims struct {
   Subject int64  `json:"sub"`
   Prv     string `json:"prv"`
   jwt.StandardClaims
}

func NewJWT(secret string) *JWT {
   return &JWT{SigningKey: []byte(secret)}
}

//创建token
func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
   token := jwt.New(jwt.SigningMethodHS256)
   token.Claims = claims
   res, err := token.SignedString(j.SigningKey)
   fmt.Println("err:", err)
   return res, err
}

//解析token
func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {

   token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
      if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
         log.Panicln("unexpected signing method")
         return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
      }
      return j.SigningKey, nil
   })

   if err != nil {
      return nil, err
   }

   if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
      return claims, nil
   }
   return nil, TokenInvalid
}

//更新token
func (j *JWT) RefreshToken(tokenString string) (string, error) {
   token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
      return j.SigningKey, nil
   })

   if err != nil {
      return "", err
   }

   if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
      claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
      return j.CreateToken(*claims)
   }

   return "", TokenInvalid
}

func (j *JWT) GenerateToken(uid int64) (string, error) {

   now := int64(time.Now().Unix())

   claims := CustomClaims{
      uid,
      "23bd5c8949f600adb39e701c400872db7a5976f7", jwt.StandardClaims{
         IssuedAt:  now,
         NotBefore: now - 60,
         ExpiresAt: now + 1000,
         Issuer:    "man",
      },
   }

   token, err := j.CreateToken(claims)
   if err != nil {
      return "", err
   }

   return token, nil
}

func main() {

   jwt.TimeFunc = time.Now

   tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInBydiI6IjIzYmQ1Yzg5NDlmNjAwYWRiMzllNzAxYzQwMDg3MmRiN2E1OTc2ZjciLCJleHAiOjE1ODI5NDM1NTEsImlhdCI6MTU4Mjk0MjU1MSwiaXNzIjoibWFuIiwibmJmIjoxNTgyOTQyNDkxfQ.KTP1RWWaHpcPknNTiYeE-iAY9qOJscdJ5r5BbNlYCho"

   j := NewJWT(hmacSampleSecret)
   // Parse takes the token string and a function for looking up the key. The latter is especially
   // useful if you use multiple keys for your application.  The standard is to use 'kid' in the
   // head of the token to identify which key to use, but the parsed token (head and claims) is provided
   // to the callback, providing flexibility.
   claims, err := j.ParseToken(tokenString)
   if err == nil {
      fmt.Printf("user id:%d\n", claims.Subject)
      fmt.Printf("%+v\n", claims)
   } else {
      fmt.Println(err.Error())
   }

   new_token, err := j.GenerateToken(1)
   if err != nil {
      fmt.Println(err.Error())
      return
   }
   fmt.Println(new_token)
}


  1. hmacSampleSecret 是 JWT 的密钥

  2. 23bd5c8949f600adb39e701c400872db7a5976f7 这个是 Laravel JWT 为了辨别 Token 是哪个 Model 发的添加的自定义字段 prv,其实这个字段可以用预定义的某个字段来实现的

  3. Subject 用于存放 ID,也就是 sub 字段

  4. 注意里面的过期时间。

  5. 另外,JWT 是没有失效这一说说法的。这是因为 PHP Laravel 封装的太死了。如果要失效,可以添加一个 last_login 字段当作 JWT 的 issue at。然后每次校验的时候检查下 last_login 字段是否一样即可。如果你不想用 last_login ,那么可以用其它字段,只要每次登录自动会改变即可。很多东西,没必要搞自己那么一套


本文》有 0 条评论

留下一个回复