Documentation
¶
Overview ¶
Package auth 承载用户认证体系:bcrypt 密码哈希(与 sub2api 同参数)、 JWT 签发/验证(HS256,TTL 24h)与 RBAC 中间件(/user 组 RequireJWT + 快照用户状态校验;/admin = platform_admin JWT OR platform_admin 管理 key)。
Index ¶
- Constants
- Variables
- func HashPassword(plain string) (string, error)
- func RequireIdentity(iss *Issuer, p SnapshotProvider) func(http.Handler) http.Handler
- func RequireJWT(iss *Issuer, users UserStatusProvider) func(http.Handler) http.Handler
- func RequireRole(users UserStatusProvider, roles ...domain.Role) func(http.Handler) http.Handler
- func ValidatePasswordLen(plain string) error
- func VerifyPassword(hash, plain string) bool
- type Claims
- type Issuer
- type ManagementKeyProvider
- type SnapshotProvider
- type UserStatusProvider
Constants ¶
const DefaultTTL = 24 * time.Hour
评审定夺①:JWT 密钥 config 强制(C3API_JWT_SECRET),缺失启动失败—— 随机生成 = 重启全失效 + 多实例不一致。 评审定夺②:TTL 24h(用户决策 2026-08-11,原 15min 短时效导致日常使用频繁掉线)。 降权即时生效 = adminAuth 快照 role 覆盖 claims.Role(见 internal/server/ middleware.go adminAuth——快照刷新 ≤Reload 周期即生效);TTL 只约束 token 本身有效期,快照失效后长 TTL 仍作最终兜底。
Variables ¶
var ( ErrInvalidToken = errors.New("auth: invalid token") ErrTokenExpired = errors.New("auth: token expired") )
var ErrPasswordTooLong = errors.New("auth: password exceeds 72 bytes (bcrypt limit)")
ErrPasswordTooLong bcrypt 截断限制(≤72 字节;注册/改密拒绝超长)。
Functions ¶
func HashPassword ¶
HashPassword bcrypt DefaultCost(10),与 sub2api 完全一致——sub2api 迁移 存量 hash 直接可验证(同参数)。
func RequireIdentity ¶
RequireIdentity /user 组(含供应商面)统一身份鉴权中间件(spec 2026-10-09 §4.3): Bearer 凭证既可为 JWT(eyJ…)亦可为管理 key(mk-…),二者均以 owner/user 身份 放行。单一 SnapshotProvider(users + mgmt 合并)——同一 auth 只传一次。前缀先判:
- mk- 开头 → 管理 key 快照查表(失败/禁用 → 401,**不回落 JWT**),owner 快照 缺失/非 active → 401(fail-closed);成功注入 Claims{UserID, Ver:sn.TokenVersion, Role:sn.Role} + FundsActor{UserID, TokenVersion:sn.TokenVersion}。
- 非 mk- → 既有 JWT 校验(Verify + 快照 status/TokenVersion),同样注入 Claims + FundsActor。
两条分支都注入 ctxClaimsKey(下游 RequireRole / SupplierScopeInject / handler 读 auth.ClaimsFrom)与 FundsActor(资金命令 actor = owner,token_version = owner 快照 当前值——与 JWT 路径逐位一致,资金写事务复核通过)。不改动导出的 RequireJWT (他处/测试仍用)。
func RequireJWT ¶
RequireJWT /user 组中间件:验证 Bearer JWT + 内存快照用户状态校验。 用户禁用 → 立即拒绝(快照刷新走 invalidate);JWT 24h 长时效仅作快照 失效后的最终兜底(评审定夺②,用户决策 2026-08-11)。
func RequireRole ¶
RequireRole 端点级 RBAC 声明:**快照 role ∈ 允许角色**(fail-closed—— 快照缺失即拒;与 RequireJWT/adminAuth 同源快照,降权在下一次成功 auth-sync 刷新后生效,§2.6)。就地改造为快照基(原读 claims.Role;RequireJWT 与 adminAuth 均读快照,本函数须一致,否则违反 fail-closed)。supplier 面用法: RequireJWT(users) → RequireRole(users, domain.SupplierSurfaceRoles()...)。
func ValidatePasswordLen ¶
ValidatePasswordLen 密码 ≤72 字节校验(bcrypt 截断限制;超长拒绝而非 静默截断)。
func VerifyPassword ¶
VerifyPassword 校验明文与 bcrypt hash(sub2api 同参数 hash 直接可验证)。
Types ¶
type Claims ¶
type Claims struct {
UserID int64 `json:"user_id"`
Email string `json:"email"`
Role string `json:"role"`
Ver int64 `json:"ver"`
jwt.RegisteredClaims
}
Claims JWT 载荷:userID/email/role/ver/exp(HS256)。Ver = 签发时的 users.token_version 快照(spec 2026-08-25-jwt-password-revocation):改密/ 重置密码原子递增版本号,RequireJWT/adminAuth 与内存快照比对,不等 → 401 ——撤销该用户全部既有 JWT,无需 Redis denylist(版本语义"只认最新", 天然有界零额外读;存量票 ver 缺失解码 0 = DB 默认 0 ⇒ 升级平滑)。
type Issuer ¶
type Issuer struct {
// contains filtered or unexported fields
}
Issuer JWT 签发/验证器(单实例;HS256)。
type ManagementKeyProvider ¶
type ManagementKeyProvider interface {
AuthenticateManagement(r *http.Request) (domain.ManagementKeyMeta, bool)
}
ManagementKeyProvider 管理 key 鉴权快照面(proxy.Auth 实现,spec 2026-10-09): 仅认 Authorization: Bearer mk-…;前缀先判、失败不回退 JWT(由调用方纪律保证)。
type SnapshotProvider ¶
type SnapshotProvider interface {
UserStatusProvider
ManagementKeyProvider
}
SnapshotProvider 单一鉴权快照面(spec 2026-10-09 §4.3):合并用户状态与 管理 key 两个 provider——同一 auth 只传一次。proxy.Auth 同时实现两者。
type UserStatusProvider ¶
type UserStatusProvider interface {
UserSnapshot(userID int64) (domain.UserSnapshot, bool)
}
UserStatusProvider 用户快照(status+role 单次查找;proxy.Auth 实现;用户 变更走 invalidate → Auth.Reload 全量刷新,RequireJWT/adminAuth 不用 DB 直查——评审定夺②)。