package jwt import ( "errors" "fmt" "time" "github.com/golang-jwt/jwt/v5" ) const ( // TokenExpiration Token过期时间(7天) TokenExpiration = 7 * 24 * time.Hour ) var ( // jwtSecret JWT签名密钥(应该从环境变量或配置文件读取) jwtSecret = []byte("your-secret-key-change-in-production") ) // SetSecret 设置JWT签名密钥(应该在服务启动时调用) func SetSecret(secret string) { jwtSecret = []byte(secret) } // Claims JWT Claims结构 type Claims struct { UserID int64 `json:"user_id"` StarID int64 `json:"star_id"` UpdatedAt int64 `json:"updated_at"` jwt.RegisteredClaims } // GenerateToken 生成JWT Token func GenerateToken(userID, starID int64, updatedAt int64) (string, error) { now := time.Now() expiresAt := now.Add(TokenExpiration) claims := Claims{ UserID: userID, StarID: starID, UpdatedAt: updatedAt, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(expiresAt), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtSecret) if err != nil { return "", fmt.Errorf("failed to sign token: %w", err) } return tokenString, nil } // ParseToken 解析JWT Token(不验证过期时间,用于刷新Token场景) func ParseToken(tokenString string) (*Claims, error) { 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 jwtSecret, nil }) if err != nil { return nil, fmt.Errorf("failed to parse token: %w", err) } claims, ok := token.Claims.(*Claims) if !ok || !token.Valid { return nil, errors.New("invalid token claims") } return claims, nil } // ValidateToken 验证Token(检查签名和过期时间) func ValidateToken(tokenString string) (*Claims, error) { claims, err := ParseToken(tokenString) if err != nil { return nil, err } // 验证过期时间 if claims.ExpiresAt != nil && claims.ExpiresAt.Time.Before(time.Now()) { return nil, errors.New("token expired") } return claims, nil } // GetExpiresAt 获取Token过期时间戳(毫秒) func GetExpiresAt() int64 { return time.Now().Add(TokenExpiration).UnixMilli() } // GetExpiresIn 获取Token过期时间(秒) func GetExpiresIn() int64 { return int64(TokenExpiration.Seconds()) }