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 }