Files

62 lines
1.4 KiB
Go

package jwt
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
"time"
)
type Jwt struct {
Key []byte
TokenExpireDuration time.Duration
}
type UserClaims struct {
UserId uint `json:"user_id"`
jwt.RegisteredClaims
}
func NewJwt(key string, tokenExpireDuration time.Duration) *Jwt {
return &Jwt{
Key: []byte(key),
TokenExpireDuration: tokenExpireDuration,
}
}
func (s *Jwt) GenerateToken(userId uint) string {
if len(s.Key) == 0 {
fmt.Println("jwt key is nil")
return ""
}
t := jwt.NewWithClaims(jwt.SigningMethodHS256,
UserClaims{
UserId: userId,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(s.TokenExpireDuration)),
// 每次登录生成唯一 jti,避免同一账号同秒多次登录产生相同 token,
// 导致 UserToken 表中 token 无法区分设备
ID: uuid.NewString(),
},
})
token, err := t.SignedString(s.Key)
if err != nil {
fmt.Printf("jwt token generate error: %v", err)
return ""
}
return token
}
func (s *Jwt) ParseToken(tokenString string) (uint, error) {
token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
return s.Key, nil
})
if err != nil {
return 0, err
}
if claims, ok := token.Claims.(*UserClaims); ok && token.Valid {
return claims.UserId, nil
}
return 0, err
}