Files
lone-services/pkg/utils/jwt.go
T
2026-09-02 17:37:12 +08:00

96 lines
2.3 KiB
Go

package utils
import (
"errors"
"fmt"
"strconv"
"time"
"github.com/golang-jwt/jwt/v4"
)
const (
TokenTypeAccess = "access"
TokenTypeRefresh = "refresh"
)
type JWT struct {
Secret string
TTL int
Issuer string
}
func NewJWT(secret, issuer string, ttlSeconds int) (*JWT, error) {
if secret == "" {
return nil, errors.New("jwt secret empty")
}
if ttlSeconds < 1 {
return nil, errors.New("jwt ttl invalid")
}
return &JWT{
Secret: secret,
TTL: ttlSeconds,
Issuer: issuer,
}, nil
}
type Claims struct {
UserID int64 `json:"user_id"`
Name string `json:"name"`
Avatar string `json:"avatar"`
Mobile string `json:"mobile"`
Gender uint8 `json:"gender"`
Birthday string `json:"birthday"`
Type uint8 `json:"type"` // 1销售 2门店 3普通用户
ClientCode string `json:"client_code"`
SaleId int64 `json:"sale_id,omitempty"`
StoreId int64 `json:"store_id,omitempty"`
TokenType string `json:"token_type"` // access | refresh
jwt.RegisteredClaims
}
func (j *JWT) Sign(claims Claims) (string, error) {
if j == nil {
return "", errors.New("jwt not initialized")
}
now := time.Now()
claims.Issuer = j.Issuer
claims.IssuedAt = jwt.NewNumericDate(now)
claims.ExpiresAt = jwt.NewNumericDate(now.Add(time.Duration(j.TTL) * time.Second))
claims.ID = strconv.FormatInt(claims.UserID, NumberTen)
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(j.Secret))
}
func (j *JWT) Parse(tokenString string) (*Claims, error) {
if j == nil {
return nil, errors.New("jwt not initialized")
}
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(j.Secret), nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*Claims)
if !ok || !token.Valid {
return nil, errors.New("invalid token")
}
return claims, nil
}
func (j *JWT) ParseExpect(tokenString, expectType string) (*Claims, error) {
claims, err := j.Parse(tokenString)
if err != nil {
return nil, err
}
if claims.TokenType != expectType {
return nil, fmt.Errorf("unexpected token type: %s", claims.TokenType)
}
return claims, nil
}