Loading

Golang Jwt集成

Jwt

Github: https://github.com/golang-jwt/jwt
文档:https://pkg.go.dev/github.com/golang-jwt/jwt

拉取仓库

go get https://github.com/golang-jwt/jwt

代码编写

配置文件

jwt:
  key: "WXlqEk8BJXmAjtp" // 随机生成

定义 Payload 结构体 和 逻辑代码

request.go

package jwtauth

import (
	"errors"
	"github.com/golang-jwt/jwt"
	"go.uber.org/zap"
	"micro-shop-api/user-web/global"
	"time"
)

// CustomClaims 自定义 Payload 信息
type CustomClaims struct {
	Id       uint   // 用户id
	Mobile   string // 手机号
	Nickname string // 用户昵称
	jwt.StandardClaims
}

func NewCustomClaimsDefault(id uint, mobile string, nickname string) *CustomClaims {
	beforeTime := time.Now().Unix()
	return &CustomClaims{
		Id:       id,
		Mobile:   mobile,
		Nickname: nickname,
		StandardClaims: jwt.StandardClaims{
			NotBefore: beforeTime, // 生效时间
			ExpiresAt: beforeTime + 60*60*24, // 失效时间
			Issuer:    "lzscxb", // 机构
		},
	}
}

type JWT struct {
	singKey []byte // Jwt 密钥
}

var (
	TokenExpired     = errors.New("Token is expired")        // 令牌过期
	TokenNotValidYet = errors.New("Token not active yet")    // 令牌未生效
	TokenMalformed   = errors.New("that's not even a token") // 令牌不完整
	TokenInvalid     = errors.New("")                        // 无效令牌
)

// NewJWT 返回一个JWT 实例
func NewJWT() *JWT {
	return &JWT{
		singKey: []byte(global.Config.JwtInfo.SingKey),
	}
}

// CreateToken 创建新的 Token
func (j *JWT) CreateToken(claims CustomClaims) (token string, err error) {
	withClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return withClaims.SignedString(j.singKey)
}

// ParseToken 验证 Token
func (j *JWT) ParseToken(token string) (*CustomClaims, error) {
	withClaims, err := jwt.ParseWithClaims(token, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		return j.singKey, nil
	})
	if err != nil {
		// 获取到 Jwt ValidationError 错误类型
		if ve, ok := err.(*jwt.ValidationError); ok {
			zap.S().Infof("获取到 Jwt ValidationError 原:%v 错误类型:%v", err, ve.Errors)
			if ve.Errors&jwt.ValidationErrorMalformed != 0 { // 令牌不完整
				return nil, TokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 { // 令牌过期
				return nil, TokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { // 令牌还未生效
				return nil, TokenNotValidYet
			} else {
				return nil, TokenInvalid
			}
		}
		return nil, TokenInvalid
	}
	if withClaims == nil {
		return nil, TokenInvalid
	}

	if claims, ok := withClaims.Claims.(*CustomClaims); ok { // 验证成功	
		return claims, nil
	} 
    return nil, TokenInvalid

}

示例

生成 Token

j := jwtauth.NewJWT()
claims := jwtauth.NewCustomClaimsDefault(uint(id),mobile, nickname)
token, err := j.CreateToken(*claims)
if err != nil {
    return
}
fmt.Println(token)

中间件验证 Token

func JwtAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取 header 中的 token
		token := c.GetHeader("Authorization")
		j := jwtauth.NewJWT()
		// 验证 token
		claims, err := j.ParseToken(token)
		if err != nil { 
            // 验证失败
			c.Abort() // 中断,中间件中 return 不生效
		}
		c.Set("uid", claims.Id)
		c.Set("mobile", claims.Mobile)
		c.Next()
	}
}

使用中间件

UserRoute := router.Group("user").Use(middleware.JwtAuth())
posted @ 2022-06-07 13:30  白日醒梦  阅读(196)  评论(0编辑  收藏  举报