package jwtx import ( "cn/oneao/base-go/conf" "sync" "time" "github.com/golang-jwt/jwt/v4" ) type CustomClaims struct { UserID int64 `json:"user_id"` jwt.RegisteredClaims } type TokenResult struct { Claims *CustomClaims IsValid bool IsExpired bool } type jwtManager struct { secret string accessExpiry time.Duration refreshExpiry time.Duration } var ( manager *jwtManager once sync.Once ) // InitJwt 初始化全局 JWT 配置,只能调用一次 func InitJwt() { once.Do(func() { manager = &jwtManager{ secret: conf.GetConf().JWT.Secret, accessExpiry: conf.GetConf().JWT.AccessExpiry, refreshExpiry: conf.GetConf().JWT.RefreshExpiry, } }) } // CreateAccessToken 全局函数创建 Access Token func CreateAccessToken(userID int64) (string, error) { return manager.createToken(userID, manager.accessExpiry) } // CreateRefreshToken 全局函数创建 Refresh Token func CreateRefreshToken(userID int64) (string, error) { return manager.createToken(userID, manager.refreshExpiry) } // VerifyToken 全局函数验证 Token func VerifyToken(tokenString string) TokenResult { result := TokenResult{IsValid: false, IsExpired: false} if tokenString == "" || manager == nil { return result } token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(manager.secret), nil }) if token == nil { return result } claims, ok := token.Claims.(*CustomClaims) if !ok { return result } if err != nil || !token.Valid { return result } result.Claims = claims result.IsValid = true if claims.ExpiresAt != nil && time.Now().After(claims.ExpiresAt.Time) { result.IsExpired = true } return result } // 内部方法,生成 Token func (j *jwtManager) createToken(userID int64, expiry time.Duration) (string, error) { claims := &CustomClaims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(time.Now()), }, } switch { case expiry > 0: claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(expiry)) case expiry == -1: claims.ExpiresAt = nil // 永不过期 default: claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(time.Hour)) } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(j.secret)) }