3. 签名链路定义与场景
在多租户微服务架构中,数字签名不再是一次性、端到端的操作,而是形成了一条贯穿多个服务节点的签名链路。本章将明确定义签名链路的核心概念,解析数字签名在微服务间的传递流程与验证链,并给出多租户场景下的典型拓扑结构。
3.1 签名链路的基本定义
签名链路是指一个业务请求从入口网关开始,经过多个微服务节点,在每个节点上依次进行签名验证、上下文传递、以及可能的重签名或附加签名,最终到达目标服务或返回客户端的完整路径。
签名链路区别于普通请求链路的关键特征:
| 特征 | 普通请求链路 | 签名链路 |
|---|---|---|
| 数据完整性 | 依赖传输层 TLS | 应用层数字签名 + TLS 双重保障 |
| 身份绑定 | 仅验证服务身份(mTLS) | 验证调用方租户身份 + 用户身份 + 服务身份 |
| 防篡改粒度 | 传输中数据包 | 请求体 + 关键头部 + 时间戳 + 租户上下文 |
| 跨服务传递 | 透传 HTTP 头部 | 透传签名载荷 + 签名值 + 证书链 |
| 审计追溯 | 依赖日志聚合 | 签名链本身提供不可抵赖的审计证据 |
关键认知: 签名链路不是对 TLS 的替代,而是在应用层构建的、与租户身份绑定的信任传递链。TLS 保证通道安全,签名链路保证内容可信与租户隔离。
3.2 数字签名在微服务间的传递流程
一个完整的签名传递流程包含以下步骤,以 Istio Sidecar 代理模式为背景:
- 客户端签名:客户端(或入口网关)使用租户私钥对请求体 + 租户 ID + 时间戳 + 随机数进行签名,生成签名值
sig_client,并附加在请求头部。 - Sidecar 拦截与验证:Istio Sidecar(Envoy)通过自定义 Filter 拦截请求,提取签名头部,调用验证服务或本地公钥缓存验证
sig_client。 - 上下文注入:验证通过后,Sidecar 将验证结果(租户 ID、签名时间、签名算法)注入到请求的
x-signature-context头部,供下游服务使用。 - 服务间转发:服务 A 处理完业务逻辑后,将原始签名载荷 + 自身签名(
sig_service_a)附加到请求中,转发给服务 B。 - 递归验证:服务 B 的 Sidecar 验证
sig_client和sig_service_a,形成签名链的累积验证。 - 最终验证:目标服务收到请求时,可获取完整的签名链列表,进行端到端的完整性校验。
传递流程要点:
- 每个服务节点既验证上游签名,也附加自身签名,形成链式信任。
- 签名载荷中必须包含租户 ID,确保多租户场景下的隔离性。
- 时间戳和随机数用于防止重放攻击。
3.3 签名验证链的结构
签名验证链是一个有序的签名列表,每个元素包含签名者身份、签名值、签名时间、被签名数据摘要。验证链的典型结构如下:
签名验证链 (Signature Chain)
├── 节点 1: 客户端 (租户 A)
│ ├── 签名算法: ECDSA-P256
│ ├── 签名时间: 2025-01-15T10:30:00Z
│ ├── 签名值: sig_client_base64
│ └── 被签名数据: body_hash + tenant_id + timestamp + nonce
├── 节点 2: 服务 A (gateway-svc)
│ ├── 签名算法: Ed25519
│ ├── 签名时间: 2025-01-15T10:30:01Z
│ ├── 签名值: sig_service_a_base64
│ └── 被签名数据: sig_client + body_hash + tenant_id
└── 节点 3: 服务 B (order-svc)
├── 签名算法: Ed25519
├── 签名时间: 2025-01-15T10:30:02Z
├── 签名值: sig_service_b_base64
└── 被签名数据: sig_service_a + body_hash + tenant_id
验证链的验证规则:
- 顺序验证:从链头开始,依次验证每个签名,前一个签名验证通过后才能验证下一个。
- 数据完整性:每个签名都包含对前一个签名值的摘要,形成哈希链,任何中间篡改都会导致后续验证失败。
- 租户一致性:所有签名中的
tenant_id必须一致,否则视为跨租户攻击。 - 时间窗口:相邻签名的时间差不能超过配置阈值(默认 5 秒),防止签名被延迟重放。
3.4 多租户签名链路的典型拓扑
在多租户环境中,签名链路需要同时处理租户隔离和服务共享的矛盾。以下给出两种典型拓扑:
3.4.1 集中式验证拓扑
所有签名验证集中在一个专用的签名验证服务(SVS)中完成,业务服务只负责透传签名载荷。这种拓扑适用于租户数量较少、对延迟不敏感的场景。
3.4.2 分布式验证拓扑
每个服务的 Sidecar 代理本地完成签名验证,验证结果通过请求头部透传。这种拓扑适用于租户数量多、对延迟敏感的场景,也是 Istio 多租户签名链路的主流方案。
3.5 拓扑对比与选型建议
| 对比维度 | 集中式验证拓扑 | 分布式验证拓扑 |
|---|---|---|
| 验证延迟 | 高(每次验证需 RPC 调用 SVS) | 低(本地验证,缓存公钥) |
| 单点瓶颈 | SVS 可能成为瓶颈 | 无单点,水平扩展 |
| 租户扩展性 | 受限于 SVS 性能 | 随服务实例数线性扩展 |
| 运维复杂度 | 低(集中管理签名策略) | 中(需管理 Sidecar 配置与公钥分发) |
| 审计追溯 | SVS 日志集中 | 签名链头部自带审计信息 |
| Istio 集成度 | 需额外部署 SVS | 原生集成,通过 Envoy Filter 实现 |
选型建议:
- 租户数量 < 100、对延迟不敏感、团队运维能力有限 → 优先选择集中式拓扑。
- 租户数量 > 1000、要求低延迟(P99 < 5ms)、已有 Istio 基础设施 → 优先选择分布式拓扑。
- 中间规模(100~1000 租户)→ 可采用混合模式:关键路径分布式验证,非关键路径集中验证。
3.6 签名链路中的关键头部设计
在 Istio 环境下,签名链路的上下文通过 HTTP 头部传递。以下是一组推荐的头部设计:
| 头部名称 | 类型 | 说明 | 示例值 |
|---|---|---|---|
x-signature-value |
请求 | 当前节点的签名值(Base64 编码) | MEUCIQD... |
x-signature-algorithm |
请求 | 签名算法标识 | ECDSA-P256 |
x-signature-timestamp |
请求 | 签名生成时间(Unix 毫秒时间戳) | 1736922600000 |
x-signature-chain |
请求 | 累积的签名链(JSON 数组,每个元素包含签名者、签名值、时间戳) | [{"signer":"client","sig":"...","ts":...},...] |
x-signature-context |
请求 | 验证结果上下文(由 Sidecar 注入,包含租户 ID、验证状态、签名者身份) | tenant_id=tenant-a;verified=true;signer=gateway |
x-signature-nonce |
请求 | 防重放随机数 | a1b2c3d4e5f6 |
头部传递规则:
x-signature-value和x-signature-algorithm在每个服务节点被替换为当前节点的签名。x-signature-chain是累积的,每个节点在尾部追加自己的签名信息。x-signature-context由 Sidecar 注入,业务服务只读不写。- 所有签名头部必须包含在 Istio 的
request_headers_to_propagate列表中,确保跨服务透传。