Go-JWT完整示例

依赖安装

go get -u github.com/golang-jwt/jwt/v5

文档地址

文档

创建对象

jwt的相关配置

# jwt configuration
jwt:
  signing-key: xxx
  expires-time: 7d
  buffer-time: 1d
  issuer: fancy_fish
  claim-strings: fancy_fish_to_do_list

claims类型配置

package request

import (
	"github.com/golang-jwt/jwt/v5"
	"github.com/google/uuid"
)

type BaseClaims struct {
	UUID     uuid.UUID
	Username string
	jwt.RegisteredClaims
}

type CustomClaims struct {
	BaseClaims
	BufferTime int64
	jwt.RegisteredClaims
}

代码示例

package util

import (
	"ToDoList/enum"
	"ToDoList/global"
	"ToDoList/model/request"
	"fmt"
	"github.com/gin-gonic/gin"
	jwt "github.com/golang-jwt/jwt/v5"
	"net"
	"time"
)

type _jwt struct {
	SigningKey []byte
	Claims     jwt.Claims
}
// 解析token 验证是否有效
func (receiver *_jwt) ValidateToken(tokenString string) (*request.CustomClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
		return receiver.SigningKey, nil
	})
	if err != nil {
		fmt.Println(err, "token验证错误")
		return nil, err
	}
	if token != nil {
		if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
			return claims, nil
		}
		return nil, enum.TokenInvalid

	} else {
		return nil, enum.TokenInvalid
	}
}

func (receiver *_jwt) CreateToken(claims request.CustomClaims) (string, error) {
	t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := t.SignedString(receiver.SigningKey)
	if err != nil {
		fmt.Println("toen生成失败")
		return token, err
	}
	return token, nil
}

// 创建生成token必须的clasims
func (receiver *_jwt) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims {
	// 按天解析,time.ParseDuration()不支持按天。
	bft, _ := BasicUtils.ParseDuration(global.GVA_CONFIG.JWT.BufferTime)
	ept, _ := BasicUtils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
	claims := request.CustomClaims{
		BaseClaims: baseClaims,
		BufferTime: int64(bft / time.Second), // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
		RegisteredClaims: jwt.RegisteredClaims{
			Audience:  jwt.ClaimStrings{global.GVA_CONFIG.JWT.ClaimStrings}, // 受众
			NotBefore: jwt.NewNumericDate(time.Now().Add(-1000)),            // 签名生效时间
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(ept)),              // 过期时间 7天  配置文件
			Issuer:    global.GVA_CONFIG.JWT.Issuer,                         // 签名的发行者
		},
	}
	return claims
}

func JWTNew() *_jwt {
	return &_jwt{
		SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey),
	}
}

var JWTToken = JWTNew()

func SetToken(c *gin.Context, token string, maxAge int) {
	// 增加cookie x-token 向来源的web添加
	host, _, err := net.SplitHostPort(c.Request.Host)
	if err != nil {
		host = c.Request.Host
	}

	if net.ParseIP(host) != nil {
		c.SetCookie("x-token", token, maxAge, "/", "", false, false)
	} else {
		c.SetCookie("x-token", token, maxAge, "/", host, false, false)
	}
}

func GetToken(c *gin.Context) string {
	token, _ := c.Cookie("x-token")
	if token == "" {
		token = c.Request.Header.Get("x-token")
	}
	return token
}

按天解析时间

func (receiver basicUtils) ParseDuration(d string) (time.Duration, error) {
	d = strings.TrimSpace(d)
	dr, err := time.ParseDuration(d)
	if err == nil {
		return dr, nil
	}
	if strings.Contains(d, "d") {
		index := strings.Index(d, "d")

		hour, _ := strconv.Atoi(d[:index])
		dr = time.Hour * 24 * time.Duration(hour)
		ndr, err := time.ParseDuration(d[index+1:])
		if err != nil {
			return dr, nil
		}
		return dr + ndr, nil
	}
	dv, err := strconv.ParseInt(d, 10, 64)
	return time.Duration(dv), err
}

生成token

	j := util.JWTNew()
	claims := j.CreateClaims(request.BaseClaims{
		UUID:     u.UUID,
		Username: u.Username,
	})
	token, err := j.CreateToken(claims)

总结

Token的组成成分

  1. 秘钥这个自定义一个字符串即可
  2. 声明名称的列表可以将用户名或 ID 或角色编码到令牌中,也可以称为载荷
  3. 签名算法
    关键函数的签名
    func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *Token

JWT-GO使用主要有以下步骤

  1. 配置私钥
  2. NewWithClaims传入方法和声明
  3. 通过SignedString创建token
  4. ParseWithClaims传入token解析token
  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鲤余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值