auth

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2026 License: MIT Imports: 13 Imported by: 0

README

Auth 组件

auth 是 Genesis 的 L3 治理层组件,提供基于 JWT 的双令牌认证能力。它适合"应用自己签发 access token / refresh token,并在服务端本地完成验签"的场景,重点解决统一签发、统一校验、统一 Gin 接入的问题。

如果你需要的是:

  • 轻量、无存储的认证方案;
  • 业务接口只接收 access token;
  • access token 过期后用 refresh token 换发新 token;
  • 在 Gin 项目里快速接入认证和简单 RBAC;

那么当前 auth 组件是合适的。

如果你需要的是:

  • token 撤销、黑名单、单设备登录;
  • refresh token 重放检测;
  • OAuth2 / OIDC / SSO;
  • 统一身份中心或外部 IdP 联动;

那么当前 auth 不覆盖这些能力。


快速开始

1. 初始化认证器
authenticator, err := auth.New(&auth.Config{
    SecretKey:       "your-secret-key-at-least-32-chars",
    SigningMethod:   "HS256",
    Issuer:          "my-service",
    Audience:        []string{"frontend"},
    AccessTokenTTL:  15 * time.Minute,
    RefreshTokenTTL: 7 * 24 * time.Hour,
    TokenHeadName:   "Bearer",
}, auth.WithLogger(logger))
2. 登录时签发双令牌
claims := &auth.Claims{
    RegisteredClaims: jwt.RegisteredClaims{
        Subject: "user-123",
    },
    Username: "alice",
    Roles:    []string{"admin"},
}

pair, err := authenticator.GenerateTokenPair(ctx, claims)
if err != nil {
    return err
}

// pair.AccessToken     用于业务接口访问
// pair.RefreshToken    用于刷新
// pair.AccessTokenExpiresAt / RefreshTokenExpiresAt 可返回给前端做过期管理
// pair.AuthorizationScheme 表示 Authorization 头前缀,默认是 "Bearer"
3. 业务接口使用 access token
r := gin.Default()
r.Use(authenticator.GinMiddleware())

r.GET("/profile", func(c *gin.Context) {
    claims, _ := auth.GetClaims(c)
    c.JSON(200, gin.H{
        "user_id": claims.Subject,
        "roles":   claims.Roles,
    })
})
4. 刷新接口使用 refresh token
r.POST("/refresh", func(c *gin.Context) {
    var req struct {
        RefreshToken string `json:"refresh_token"`
    }
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": "bad request"})
        return
    }

    pair, err := authenticator.RefreshToken(c.Request.Context(), req.RefreshToken)
    if err != nil {
        c.JSON(401, gin.H{"error": "unauthorized"})
        return
    }

    c.JSON(200, pair)
})

核心接口

type Authenticator interface {
    GenerateTokenPair(ctx context.Context, claims *Claims) (*TokenPair, error)
    ValidateAccessToken(ctx context.Context, token string) (*Claims, error)
    ValidateRefreshToken(ctx context.Context, token string) (*Claims, error)
    RefreshToken(ctx context.Context, refreshToken string) (*TokenPair, error)
    GinMiddleware() gin.HandlerFunc
}
Claims
type Claims struct {
    jwt.RegisteredClaims

    TokenType TokenType      `json:"typ,omitempty"`
    Username  string         `json:"uname,omitempty"`
    Roles     []string       `json:"roles,omitempty"`
    Extra     map[string]any `json:"extra,omitempty"`
}

说明:

  • TokenType 由组件内部写入,业务方通常不需要手动设置。
  • UsernameRolesExtra 用于承载业务身份信息。
  • GenerateTokenPair 会复制输入 claims,不会修改原对象。
TokenPair
type TokenPair struct {
    AccessToken           string
    RefreshToken          string
    AccessTokenExpiresAt  time.Time
    RefreshTokenExpiresAt time.Time
    AuthorizationScheme   string
}

说明:

  • AuthorizationScheme 表示 HTTP Authorization 头里的认证方案,默认是 Bearer
  • 它不是 JWT claims 里的 TokenType,不会返回 accessrefresh

配置

字段 默认值 说明
SecretKey 必填 HMAC 签名密钥,至少 32 字符
SigningMethod HS256 当前仅支持 HS256
Issuer 可选签发者约束
Audience 可选受众约束
AccessTokenTTL 15m access token 有效期
RefreshTokenTTL 7d refresh token 有效期
TokenLookup access token 提取方式,留空使用默认多源查找
TokenHeadName Bearer Authorization header 前缀
Access Token 提取方式

GinMiddleware() 内部只负责提取和校验 access token

TokenLookup 留空时,提取顺序为:

  1. Authorization: Bearer <token>
  2. ?token=<token>
  3. jwt=<token> cookie

如果希望只从固定来源提取,可配置:

&auth.Config{
    SecretKey:   "...",
    TokenLookup: "header:Authorization",
}

Gin 集成

认证中间件

GinMiddleware() 的语义是:

  • 自动提取 access token;
  • 自动校验签名、过期时间、issuer、audience;
  • 拒绝 refresh token 直接访问业务接口;
  • 验证成功后把 claims 放进 gin.Context
角色校验

RequireRoles 采用 OR 逻辑

r.GET("/admin", auth.RequireRoles("admin"), handler)
r.GET("/moderate", auth.RequireRoles("admin", "moderator"), handler)

这表示用户只要拥有任意一个指定角色即可通过。


前端交互模型

推荐的前端使用方式是:

  1. 登录成功后保存 access_tokenrefresh_token
  2. 普通业务请求只携带 access_token
  3. 当业务接口因 access token 过期返回 401 时,前端调用刷新接口。
  4. 刷新接口使用 refresh_token 换发新的 TokenPair
  5. 刷新失败则清理本地登录态并跳转登录页。

也就是说,普通业务请求不需要同时携带两个 token


指标

当前组件导出两个指标常量:

指标名 类型 标签 说明
auth_tokens_validated_total Counter status, error_type token 校验次数
auth_tokens_refreshed_total Counter status token 刷新次数

注意:

  • token 缺失不计入校验失败指标;
  • 当前指标没有区分 access / refresh 类型;
  • 若未来需要更细的观测维度,可在后续版本扩展。

边界与限制

当前 auth 组件明确不提供以下能力:

  • token 撤销;
  • 黑名单;
  • 单设备登录;
  • refresh token 持久化;
  • refresh token 重放检测;
  • OAuth2 / OIDC / SSO。

因此,它更适合作为应用自建认证层,而不是完整身份系统。

Documentation

Overview

Package auth 提供基于 JWT 的双令牌认证能力。

auth 是 Genesis 的 L3 治理层组件,面向"应用自己签发并校验 JWT"的场景, 提供 access token / refresh token 的签发、校验与换发能力,以及 Gin 接入层。

组件边界:

  • 提供双 JWT 令牌模型,不依赖外部存储。
  • GinMiddleware 只接受 access token。
  • RefreshToken 只接受 refresh token,并返回一对新的 token。
  • 不提供 token 撤销、会话管理、黑名单、重放检测、OAuth2/OIDC 能力。

典型用法:

authenticator, _ := auth.New(&auth.Config{SecretKey: "..."})
pair, _ := authenticator.GenerateTokenPair(ctx, &auth.Claims{
    RegisteredClaims: jwt.RegisteredClaims{Subject: "user-123"},
})
claims, _ := authenticator.ValidateAccessToken(ctx, pair.AccessToken)

Index

Constants

View Source
const (
	// MetricTokensValidated Token 验证计数,标签: status, error_type
	MetricTokensValidated = "auth_tokens_validated_total"

	// MetricTokensRefreshed Token 刷新计数,标签: status
	MetricTokensRefreshed = "auth_tokens_refreshed_total"
)
View Source
const ClaimsKey = "auth:claims"

Variables

View Source
var (
	ErrInvalidToken     = xerrors.New("auth: invalid token")
	ErrExpiredToken     = xerrors.New("auth: token expired")
	ErrMissingToken     = xerrors.New("auth: missing token")
	ErrInvalidClaims    = xerrors.New("auth: invalid claims")
	ErrInvalidSignature = xerrors.New("auth: invalid signature")
	ErrInvalidConfig    = xerrors.New("auth: invalid config")
)

Functions

func RequireRoles

func RequireRoles(roles ...string) gin.HandlerFunc

RequireRoles 要求用户拥有其中一个角色的中间件,采用 OR 逻辑 RequireRoles("admin", "editor") 表示用户必须拥有 admin 或 editor 角色之一

Types

type Authenticator

type Authenticator interface {
	// GenerateTokenPair 生成 access / refresh 双令牌。
	GenerateTokenPair(ctx context.Context, claims *Claims) (*TokenPair, error)

	// ValidateAccessToken 验证 access token,返回 Claims。
	ValidateAccessToken(ctx context.Context, token string) (*Claims, error)

	// ValidateRefreshToken 验证 refresh token,返回 Claims。
	ValidateRefreshToken(ctx context.Context, token string) (*Claims, error)

	// RefreshToken 使用 refresh token 换发新的 access / refresh 双令牌。
	RefreshToken(ctx context.Context, refreshToken string) (*TokenPair, error)

	// GinMiddleware 返回 Gin 认证中间件。
	GinMiddleware() gin.HandlerFunc
}

Authenticator 认证器接口。

func New

func New(cfg *Config, opts ...Option) (Authenticator, error)

New 创建 Authenticator。

type Claims

type Claims struct {
	// 标准声明 (包含 Subject, Issuer, ExpiresAt 等)
	jwt.RegisteredClaims

	// 业务扩展声明
	TokenType TokenType      `json:"typ,omitempty"`   // 令牌类型
	Username  string         `json:"uname,omitempty"` // 用户名
	Roles     []string       `json:"roles,omitempty"` // 角色列表
	Extra     map[string]any `json:"extra,omitempty"` // 扩展信息
}

Claims 定义了 JWT 载荷结构。

它内嵌了 jwt.RegisteredClaims 以支持标准声明(如 exp, sub, iss 等), 同时扩展了 Genesis 框架常用的业务字段。

字段说明:

  • TokenType: 令牌类型(access / refresh)。
  • Username: 用户名 (对应 uname)
  • Roles: 角色列表 (对应 roles)
  • Extra: 扩展字段 (对应 extra)

func GetClaims

func GetClaims(c *gin.Context) (*Claims, bool)

GetClaims 从 Gin Context 获取 Claims

type Config

type Config struct {
	// JWT 配置
	SecretKey     string   `mapstructure:"secret_key"`     // 签名密钥(至少 32 字符)
	SigningMethod string   `mapstructure:"signing_method"` // 签名方法: HS256(目前只支持)
	Issuer        string   `mapstructure:"issuer"`         // 签发者
	Audience      []string `mapstructure:"audience"`       // 接收者

	// Token 有效期
	AccessTokenTTL  time.Duration `mapstructure:"access_token_ttl"`  // Access Token TTL,默认 15m
	RefreshTokenTTL time.Duration `mapstructure:"refresh_token_ttl"` // Refresh Token TTL,默认 7d

	// Token 提取配置(可选,覆盖默认查找顺序)
	// 默认顺序: header:Authorization -> query:token -> cookie:jwt
	// 可指定单一来源如 "header:Authorization" 或 "query:token"
	TokenLookup   string `mapstructure:"token_lookup"`    // 提取方式,留空使用默认多源查找
	TokenHeadName string `mapstructure:"token_head_name"` // Header 前缀,默认 Bearer
}

Config Auth 配置

type Option

type Option func(*options)

Option 配置选项函数

func WithLogger

func WithLogger(l clog.Logger) Option

WithLogger 注入日志记录器,自动添加 "auth" 命名空间

func WithMeter

func WithMeter(m metrics.Meter) Option

WithMeter 注入指标 Meter

type TokenPair added in v0.5.0

type TokenPair struct {
	AccessToken           string
	RefreshToken          string
	AccessTokenExpiresAt  time.Time
	RefreshTokenExpiresAt time.Time
	AuthorizationScheme   string
}

TokenPair 表示一对 access / refresh 令牌。

type TokenType added in v0.5.0

type TokenType string

TokenType 表示 JWT 的业务用途类型。

const (
	// TokenTypeAccess 表示访问令牌。
	TokenTypeAccess TokenType = "access"

	// TokenTypeRefresh 表示刷新令牌。
	TokenTypeRefresh TokenType = "refresh"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL