3.8 KiB
3.8 KiB
平台鉴权与 Token 校验中间件设计(TOK-002)
- 版本:v1.0
- 日期:2026-03-29
- 状态:开发实施设计基线
- 依赖:
docs/token_runtime_minimal_spec_v1.md - 目标:实现“仅平台凭证入站”,并为 M-014/M-016/M-021 提供可验证链路。
1. 设计目标
- 所有北向请求必须通过平台凭证校验。
- 外部
query key入站一律拒绝并记录审计事件。 - 鉴权结果可追踪到
request_id + subject_id + token_id。 - 在不泄露上游凭证的前提下返回标准错误码。
2. 适用范围
- 路由范围:
/api/v1/supply/*、/api/v1/platform/*。 - 鉴权头:仅支持
Authorization: Bearer <token>。 - 排除范围:健康检查、内部探针、公开静态资源。
3. 中间件链路
3.1 处理顺序
RequestIdMiddlewareQueryKeyRejectMiddlewareBearerExtractMiddlewareTokenVerifyMiddlewareTokenStatusCheckMiddlewareScopeRoleAuthzMiddlewareAuditEmitMiddleware
3.2 关键规则
QueryKeyRejectMiddleware- 拒绝任意
?key=、?api_key=、?token=形式外部参数。 - 返回
401 QUERY_KEY_NOT_ALLOWED。
- 拒绝任意
BearerExtractMiddleware- 无
Authorization直接401 AUTH_MISSING_BEARER。
- 无
TokenVerifyMiddleware- 校验签名、
iss、aud、exp、nbf、jti。 - 签名失败返回
401 AUTH_INVALID_TOKEN。
- 校验签名、
TokenStatusCheckMiddleware- 查询 token 状态缓存(
active/revoked/expired)。 revoked/expired返回401 AUTH_TOKEN_INACTIVE。
- 查询 token 状态缓存(
ScopeRoleAuthzMiddleware- 按路由匹配 scope;不足返回
403 AUTH_SCOPE_DENIED。
- 按路由匹配 scope;不足返回
4. 数据与缓存策略
- 状态源:
platform_token_registry(运行态主表)。 - 热缓存:
token_status_cache(TTL 30s)。 - 吊销传播:
- 吊销事件写入总线后,1~5 秒内刷新缓存。
- 验收阈值:吊销生效延迟
<= 5s。
5. 错误语义
| 场景 | HTTP | error.code | 说明 |
|---|---|---|---|
| 缺失 Bearer | 401 | AUTH_MISSING_BEARER | 请求头缺失 |
| query key 外部入站 | 401 | QUERY_KEY_NOT_ALLOWED | 边界拒绝 |
| token 无效/签名失败 | 401 | AUTH_INVALID_TOKEN | 校验失败 |
| token 已吊销/过期 | 401 | AUTH_TOKEN_INACTIVE | 状态不可用 |
| scope 不足 | 403 | AUTH_SCOPE_DENIED | 权限不足 |
6. 审计事件(TOK-004 依赖)
token.authn.successtoken.authn.failtoken.authz.deniedtoken.query_key.rejected
最小字段:
event_idrequest_idtoken_id(可空,提取失败时为空)subject_id(可空)routeresult_codeclient_ipcreated_at
7. 伪代码(实现参考)
onRequest(req):
reqId = ensureRequestId(req)
if hasExternalQueryKey(req):
emitAudit("token.query_key.rejected", reqId, route, clientIp)
return 401 QUERY_KEY_NOT_ALLOWED
bearer = parseBearer(req.headers.Authorization)
if bearer is null:
emitAudit("token.authn.fail", reqId, route, "AUTH_MISSING_BEARER")
return 401 AUTH_MISSING_BEARER
claims = verifyToken(bearer)
if verify failed:
emitAudit("token.authn.fail", reqId, route, "AUTH_INVALID_TOKEN")
return 401 AUTH_INVALID_TOKEN
status = getTokenStatus(claims.jti)
if status != active:
emitAudit("token.authn.fail", reqId, route, "AUTH_TOKEN_INACTIVE")
return 401 AUTH_TOKEN_INACTIVE
if !checkScopeRole(claims.scope, claims.role, route):
emitAudit("token.authz.denied", reqId, route, "AUTH_SCOPE_DENIED")
return 403 AUTH_SCOPE_DENIED
attachPrincipal(req, claims)
emitAudit("token.authn.success", reqId, route, "OK")
pass
8. 开发阶段验收(设计级)
- 与
TOK-001角色、状态机、审计字段一致。 - 与
M-014/M-016指标定义一致。 - 与 OpenAPI token 契约草案字段一致。