Jwt的使用

Jwt的使用

准备自定义结构体

// 存储的数据
type JwtPayLoad struct {
	UserName string `json:"username"`
	NickName string `json:"nick_name"`
	Role     int    `json:"role"`
	UserId   uint   `json:"user_id"`
	Avatar   string `json:"avatar"`
}

// 将jwt.RegisteredClaims嵌套到CustomClaims中,用来扩展自定义内容和继承Claims
type CustomClaims struct {
	JwtPayLoad
	jwt.RegisteredClaims
}

使用 NewWithClaims 函数生成 token

func NewWithClaims(method SigningMethod, claims Claims) *Token {
	return &Token{
		Header: map[string]interface{}{
			"typ": "JWT",
			"alg": method.Alg(),
		},
		Claims: claims,
		Method: method,
	}
}
// jwt.RegisteredClaims实现了Valid接口,继承了Claims
type Claims interface {
	Valid() error
}

生成 token

func GenToken(payLoad JwtPayLoad, secret string, expires int64) (string, error) {
	claim := CustomClaims{
		JwtPayLoad: payLoad,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(expires))),
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
	return token.SignedString([]byte(secret))
}

解析 token,需要密钥鉴权

func ParseToken(secret, tokenStr string) (*CustomClaims, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(t *jwt.Token) (interface{}, error) {
		return []byte(secret), nil
	})
	if err != nil {
		log.Println(fmt.Sprintf("token解析错误: %s", err.Error()))
		return nil, err
	}
	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New("token非法")
}

注意:不要在 jwt 中存储敏感信息,jwt 中的 payload 部分只是使用了 base64 对内容进行了编码,并没有加密,主要是通过 jwt 的 signature 部分对整个 jwt 进行验证

验证方式:服务器会使用与生成 jwt 时相同的密钥和签名算法,对头部和载荷重新进行签名,并将新生成的签名与 jwt 中的签名进行比较,同时检查过期时间

posted @ 2025-03-28 19:09  小依昂阳  阅读(27)  评论(0)    收藏  举报