4、签名链路原理:数字签名在微服务中的必要性、JWT与mTLS对比、请求签名流程
4.1 数字签名在微服务中的必要性
在多租户签名链路中,数字签名是保障请求完整性、来源真实性和不可抵赖性的核心技术。微服务架构下,服务间通信频繁跨越网络边界,面临以下风险:
- 中间人篡改:请求在传输过程中可能被劫持并修改负载。
- 身份伪造:攻击者冒充合法服务发起恶意请求。
- 重放攻击:捕获有效请求后重复提交。
- 租户隔离失效:多租户场景下,一个租户的签名可能被另一个租户复用。
数字签名通过私钥签名 + 公钥验签机制,确保接收方能够验证请求是否由持有对应私钥的发送方生成,且内容未被修改。在 Istio 环境中,签名通常由 Sidecar 代理(Envoy)或应用层 SDK 完成,并与服务网格的认证策略协同工作。
关键原则:签名必须覆盖请求的关键字段(如 HTTP 方法、路径、租户 ID、时间戳、请求体摘要),避免仅对部分内容签名导致的安全漏洞。
4.2 JWT 与 mTLS 对比
JWT(JSON Web )和 mTLS(双向 TLS)是微服务通信中两种主流的身份认证与签名机制。它们在实现原理、适用场景和运维复杂度上存在显著差异。
| 对比维度 | JWT(自包含令牌) | mTLS(双向 TLS) |
|---|---|---|
| 认证层级 | 应用层(HTTP 头部携带) | 传输层(TLS 握手阶段) |
| 签名机制 | 使用对称或非对称密钥对 Payload 签名 | 使用 X.509 证书进行双向身份验证 |
| 负载传递 | 令牌内包含用户/租户声明(Claims) | 证书中仅包含身份信息,不传递业务负载 |
| 性能开销 | 较低(仅需验签,无连接协商) | 较高(每次连接需 TLS 握手) |
| 密钥管理 | 需管理签名密钥(JWK)和令牌生命周期 | 需管理证书颁发机构(CA)和证书轮换 |
| 适用场景 | 跨服务、跨集群、跨组织的身份传递 | 同一信任域内的服务间通信 |
| Istio 集成 | 通过 RequestAuthentication 策略验证 |
通过 PeerAuthentication 策略启用 |
选型建议:在多租户签名链路中,通常采用JWT + mTLS 组合策略——mTLS 保障传输层安全,JWT 携带租户身份和签名信息,实现端到端的身份与完整性验证。
4.3 请求签名流程
一个完整的请求签名流程包含签名生成、传输和验签三个阶段。以下流程图展示了服务 A 向服务 B 发送签名请求的典型过程:
4.4 签名流程详细步骤
- 构造请求负载:服务 A 确定 HTTP 方法、路径、租户 ID、请求体摘要(SHA-256)、时间戳(Unix 时间戳,精度到秒)。
- 生成签名:使用服务 A 的私钥对负载进行签名(如 RS256 或 ES256),生成签名值。
- 封装 JWT:将签名值、负载声明、签发者(iss)、租户 ID(sub)、过期时间(exp)封装为 JWT 令牌。
- 附加到请求:将 JWT 放入 HTTP 请求的
Authorization: Bearer <>头部。 - 传输请求:通过 mTLS 加密通道将请求发送至服务 B。
- 提取 JWT:服务 B 的 Sidecar 或应用层从请求头部提取 JWT。
- 验签:使用服务 A 的公钥(从 JWKS 端点或本地缓存获取)验证 JWT 签名。
- 校验声明:验证时间戳是否在允许偏差范围内(通常 ±5 分钟),租户 ID 是否匹配,请求体摘要是否一致。
- 处理或拒绝:验签通过后,服务 B 处理请求;否则返回 401 Unauthorized。
4.5 签名链路关键设计点
| 设计要素 | 推荐实践 | 常见错误 |
|---|---|---|
| 签名算法 | 使用 RS256(RSA)或 ES256(ECDSA),避免使用 HS256(对称密钥) | 使用弱算法(如 HS256)导致密钥泄露风险 |
| 时间戳 | 使用 Unix 时间戳,精度到秒,偏差窗口 ≤ 300 秒 | 未校验时间戳,导致重放攻击 |
| 请求体摘要 | 对请求体计算 SHA-256 摘要,放入 JWT 的 digest 声明 |
仅签名头部,忽略请求体篡改 |
| 密钥轮换 | 使用 JWKS 端点动态分发公钥,支持 kid 标识 |
硬编码公钥,轮换困难 |
| 租户隔离 | 在 JWT 的 sub 或自定义声明中携带租户 ID |
未携带租户 ID,导致跨租户请求 |
避坑提示:在多租户场景中,务必在验签后检查 JWT 中的租户 ID 是否与请求路径或数据库中的租户 ID 一致。否则,攻击者可能使用一个租户的 JWT 访问另一个租户的资源。
4.6 Istio 中的签名集成
Istio 通过 RequestAuthentication 和 AuthorizationPolicy 资源,支持在 Sidecar 层面直接验证 JWT 签名,无需修改应用代码:
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: jwt-auth
namespace: tenant-ns
spec:
selector:
matchLabels:
app: backend-service
jwtRules:
- issuer: "service-a.tenant-cluster.local"
jwksUri: "http://jwks.tenant-cluster.local/.well-known/jwks.json"
forwardOriginalToken: true
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: tenant-ns
spec:
selector:
matchLabels:
app: backend-service
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["*"]
when:
- key: request.auth.claims[tenant_id]
values: ["tenant-123"]
上述配置实现了:
- Sidecar 自动提取并验证 JWT 签名。
- 仅允许携带有效 JWT 且租户 ID 为
tenant-123的请求通过。 - 原始 JWT 通过
forwardOriginalToken: true转发给应用层。
最佳实践:将 JWT 验签下沉到 Istio Sidecar,应用层仅需处理业务逻辑。同时,在 Sidecar 层面完成租户 ID 校验,实现多租户隔离的“零信任”模型。