// Package jwtx 轻量 JWT(HMAC-SHA256),无外部依赖。 package jwtx import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "errors" "strings" "time" ) // Claims 登录令牌载荷。 type Claims struct { Uid int64 `json:"uid"` Exp int64 `json:"exp"` Msg string `json:"msg,omitempty"` } var secret = []byte("zo-maintain-jwt-secret-2026") // Sign 签发 token(TTL 秒)。 func Sign(uid int64, ttlSeconds int64) (string, error) { payload, err := json.Marshal(Claims{Uid: uid, Exp: time.Now().Add(time.Duration(ttlSeconds) * time.Second).Unix()}) if err != nil { return "", err } body := base64.RawURLEncoding.EncodeToString(payload) sig := sign(body) return body + "." + sig, nil } // Parse 校验并解析 token。 func Parse(token string) (*Claims, error) { parts := strings.SplitN(token, ".", 2) if len(parts) != 2 { return nil, errors.New("令牌格式错误") } if sign(parts[0]) != parts[1] { return nil, errors.New("令牌签名校验失败") } payload, err := base64.RawURLEncoding.DecodeString(parts[0]) if err != nil { return nil, errors.New("令牌载荷解析失败") } var c Claims if err = json.Unmarshal(payload, &c); err != nil { return nil, errors.New("令牌载荷解析失败") } if c.Exp < time.Now().Unix() { return nil, errors.New("令牌已过期") } return &c, nil } func sign(body string) string { mac := hmac.New(sha256.New, secret) mac.Write([]byte(body)) return base64.RawURLEncoding.EncodeToString(mac.Sum(nil)) }