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

yufei       4 年, 8 月 前       1990

废话不多说,直接上代码

package main

import (
    "github.com/dgrijalva/jwt-go"
    "log"
    "fmt"
    "errors"
    "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 ,那么可以用其它字段,只要每次登录自动会改变即可。很多东西,没必要搞自己那么一套
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.