Skip to content

核心概念

本页解释 CyberGo JWT 的核心抽象与设计模型,帮助你建立整体认知。如需直接动手,请跳转 快速开始

Processor——核心类型

Processor 是库的中心类型,通过 jwt.New(cfg) 创建。它封装了令牌签发、验证、刷新和吊销的全部逻辑,所有方法并发安全,可在多个 goroutine 间共享同一实例。

使用完毕后调用 Close() 安全清除密钥并释放资源:

go
<!-- check-code: skip -->
cfg := jwt.DefaultConfig()
cfg.SecretKey = "your-32-byte-secret-key-here-minimum"

processor, err := jwt.New(cfg)
if err != nil {
    log.Fatal(err)
}
defer processor.Close()

Processor 实现了 TokenManager 接口,便于依赖注入和测试替换。

令牌生命周期

一张令牌从签发到失效,经过以下环节:

text
签发    Create(claims)           → 访问令牌(短期)
        CreateRefresh(claims)     → 刷新令牌(长期)

验证    Validate(token)          → Claims(检查签名、过期、签发者、黑名单)

刷新    Refresh(refreshToken)    → 新访问令牌

吊销    Revoke(token)            → 加入黑名单
查询    IsRevoked(token)         → bool

每个环节都返回哨兵错误(如 ErrTokenExpiredErrTokenRevoked),可通过 errors.Is() 精确匹配。详见 错误处理

双层令牌模型

CyberGo JWT 采用访问令牌 + 刷新令牌的双层设计:

访问令牌刷新令牌
用途API 认证换取新访问令牌
默认 TTL15 分钟7 天
签发方法CreateCreateRefresh
刷新方法Refresh

为什么用两层? 访问令牌有效期短,即使泄露风险窗口也小;刷新令牌有效期长但只用于换取新访问令牌,不直接用于 API 认证。这种设计在安全性与用户体验之间取得平衡——用户不必频繁登录,访问令牌过期后可静默刷新。

轮换语义

Refresh 不会自动吊销刷新令牌。原始刷新令牌在过期或显式 Revoke 之前仍然有效。如需一次性使用(refresh token rotation),请在 Refresh 成功后手动 Revoke 旧刷新令牌。详见 令牌刷新与轮换

Claims 结构

Claims 携带令牌中的用户身份数据。CyberGo JWT 提供两层结构:

RegisteredClaims(RFC 7519 标准声明,自动填充与校验):

字段claim说明
Issueriss签发方标识
Subjectsub主体标识(也用作限流键)
Audienceaud目标受众
ExpiresAtexp过期时间
NotBeforenbf生效时间
IssuedAtiat签发时间
IDjti唯一标识(黑名单键)
TokenTypetoken_typeaccessrefresh

Claims(内置业务声明,嵌入 RegisteredClaims):

go
<!-- check-code: skip -->
type Claims struct {
    UserID      string         // 用户 ID
    Username    string         // 用户名
    Role        string         // 角色
    Permissions []string       // 权限列表
    Scopes      []string       // OAuth 作用域
    SessionID   string         // 会话 ID
    ClientID    string         // 客户端 ID
    Extra       map[string]any // 额外字段
    RegisteredClaims           // 标准声明(嵌入)
}

所有字段都经过输入验证:字符串长度上限 256、数组上限 100、注入模式检测(XSS/SQLi 签名)。

CustomClaims 接口

当内置 Claims 无法满足业务需求时,实现 CustomClaims 接口定义自己的声明结构:

go
<!-- check-code: skip -->
type AppClaims struct {
    UserID string   `json:"user_id"`
    TeamID string   `json:"team_id"`
    Roles  []string `json:"roles,omitempty"`
    jwt.RegisteredClaims
}

func (c *AppClaims) GetRegisteredClaims() *jwt.RegisteredClaims {
    return &c.RegisteredClaims
}

func (c *AppClaims) Validate() error {
    if c.UserID == "" {
        return errors.New("user_id is required")
    }
    return nil
}

自定义类型通过 ValidateInto 验证、RefreshInto 刷新——Processor 会解析令牌并填充你的结构体。详见 自定义 Claims

Config 配置概览

Config 是 Processor 的统一配置入口。通过 DefaultConfig() 获取合理默认值后,只需设置密钥即可使用:

分组字段说明
签名SecretKey / SigningKey / VerificationKey / SigningMethodHMAC 用 SecretKey,RSA/ECDSA 用 SigningKey
令牌AccessTokenTTL / RefreshTokenTTL访问与刷新令牌有效期
校验Issuer / ExpectedAudience / RequireExpiration / ClockSkew签发者、受众、强制过期、时钟容忍
安全Blacklist / EnableRateLimit吊销存储与速率限制
扩展Clock时钟注入(测试用)

签名算法选型见 签名算法,完整字段说明见 配置详解

扩展接口

CyberGo JWT 通过接口实现可扩展性:

接口用途
TokenManagerProcessor 实现的核心接口。可定义自己的小子集接口(只需 Create + Validate),实现依赖注入与解耦
BlacklistStore自定义黑名单后端(如 Redis),实现 Add / Contains / Close 三方法即可对接外部存储
RateLimitProvider自定义限流器,实现 Allow / Reset / Close 即可替换内置令牌桶
ClockProvider时钟注入。FixedClock 返回固定时间,在测试中精确控制令牌过期与刷新逻辑

下一步