package jwtx import ( "allapp/config" "context" "sync" "time" "github.com/golang-jwt/jwt/v5" ) // CustomClaims 定义 JWT 自定义 Claims type CustomClaims struct { UserID int64 `json:"user_id"` jwt.RegisteredClaims } // jwtManager 单例管理 type jwtManager struct { secret string tokenExpiry time.Duration } var ( manager *jwtManager once sync.Once ) // getManager 自动初始化单例 func getManager() *jwtManager { once.Do(func() { cfg := config.GetConf().JWT manager = &jwtManager{ secret: cfg.Secret, tokenExpiry: cfg.AccessExpiry, } }) return manager } // CreateToken 生成 JWT func CreateToken(ctx context.Context, userID int64) (string, error) { m := getManager() return m.createToken(userID) } // VerifyToken 校验 token 并返回 claims func VerifyToken(ctx context.Context, tokenString string) (*CustomClaims, bool) { if tokenString == "" { return nil, false } m := getManager() token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(m.secret), nil }) if err != nil || !token.Valid { return nil, false } claims, ok := token.Claims.(*CustomClaims) if !ok { return nil, false } return claims, true } // createToken 私有方法 func (j *jwtManager) createToken(userID int64) (string, error) { now := time.Now() claims := &CustomClaims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(now), }, } if j.tokenExpiry > 0 { claims.ExpiresAt = jwt.NewNumericDate(now.Add(j.tokenExpiry)) } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(j.secret)) }