金融服务 API 网关应在高价值 API 周围建立范围清晰、能够产生证据的边界,但它不能成为账户归属、账本状态、支付最终性、欺诈或监管资格的裁决系统。安全的架构在边缘验证调用方和请求策略,再把交易授权与持久状态交给真正拥有它们的领域系统。
本文提供的是参考架构,并不声称一套网关配置可以满足所有司法辖区或合规框架。
核心要点
- 将传输身份、OAuth 客户端身份、最终用户身份、授权同意和交易授权视为相互独立的事实。
- 对生态支持的高价值机密客户端流程,优先使用发送方约束访问令牌。
- 身份、策略、撤销或配额依赖不可用时,应按预先定义的方式拒绝或降级。
- 不要把请求 ID 当作身份,也不要把审计日志当作业务交易已提交的证明。
- 日常网关遥测不得记录机密信息、账户数据或完整 Token。
从参与方和信任边界开始
1sequenceDiagram
2 participant C as 受监管客户端
3 participant G as API 网关
4 participant A as 授权服务器
5 participant P as 策略与授权同意服务
6 participant S as 金融领域服务
7 participant L as 账本或记录系统
8 C->>A: 认证并请求带 Scope 的 Token
9 A-->>C: 发送方约束访问令牌
10 C->>G: API 请求、Token 与密钥持有证明
11 G->>G: 验证传输、Token、Audience、Scope 与发送方绑定
12 G->>P: 按需检查当前策略或授权同意
13 P-->>G: 决策与策略版本
14 G->>S: 最小已验证上下文与关联 ID
15 S->>S: 授权账户与交易
16 S->>L: 应用幂等领域命令
17 L-->>S: 持久结果
18 S-->>G: 业务响应
19 G-->>C: 响应OpenID Foundation 最终版 FAPI 2.0 Security Profile面向高安全 API,同时给实现者、部署者与生态保留了一些选择。生态专用 Profile 可以进一步收窄这些选择,但不得删除或覆盖 FAPI 的强制行为。OAuth 安全最佳实践 RFC 9700建议使用双向 TLS 或 DPoP 等发送方约束 Token,降低被盗访问令牌遭滥用的风险。
RFC 8705区分了双向 TLS 客户端认证与证书绑定访问令牌。网关仅仅收到客户端证书,还不能证明所呈现的 Token 已绑定到该证书。资源服务器必须比较当前连接使用的证书与 Token 或 Introspection 结果中的证书关联关系。
把控制措施放到正确的层级
| 控制措施 | 网关角色 | 领域或平台角色 |
|---|---|---|
| TLS 与 mTLS | 验证配置的信任链,并在内部暴露已验证状态 | 证书签发、生命周期与生态注册 |
| OAuth/OIDC | 验证签名或 Introspection 结果、Issuer、Audience、时间、Scope 与发送方绑定 | 授权服务器策略与客户端注册 |
| 授权同意 | 携带已验证的授权同意引用,并执行粗粒度路由要求 | 授权同意有效性、账户范围、撤销与证据 |
| 交易授权 | 拒绝结构无效或策略禁止的请求 | 金额、收款方、账户、余额、欺诈与加强认证决策 |
| 重放与重复控制 | 限制重试并传递应用幂等键 | 原子存储幂等键、请求指纹与持久结果 |
| 审计 | 记录策略版本与网关结果 | 证明业务状态变更并保存证据 |
网关认证不等于应用授权。带有 payments:write 的 Token 可能允许访问支付路由,但只有支付服务能判断该主体是否可以从指定账户向指定收款方支付这笔金额。
使用 APISIX 构建 Bearer Token 准入层
下面的 APISIX 3.19.0 JSON 是配置片段。它假设授权服务器与客户端注册已经实现所需的金融安全 Profile。机密信息占位符必须通过获准的机密管理机制提供。
1{
2 "uri": "/payments/*",
3 "methods": ["POST"],
4 "plugins": {
5 "openid-connect": {
6 "client_id": "financial-resource-server",
7 "client_secret": "$ENV://FINANCIAL_RESOURCE_SERVER_SECRET",
8 "discovery": "https://identity.example/.well-known/openid-configuration",
9 "bearer_only": true,
10 "required_scopes": ["payments:write"],
11 "claim_validator": {
12 "audience": {
13 "required": true,
14 "match_with_client_id": true
15 }
16 },
17 "ssl_verify": true
18 }
19 },
20 "upstream": {
21 "type": "roundrobin",
22 "scheme": "https",
23 "pass_host": "node",
24 "nodes": {
25 "payments.internal:8443": 1
26 },
27 "tls": {
28 "verify": true
29 }
30 }
31}在 APISIX 3.19.0 中,bearer_only 默认为 false。设为 false 时,请求没有 Token 时插件可以使用授权码与 Session 流程;设为 true 时,该路由严格要求 Bearer 访问令牌。因此,true 适合这里面向机器的 API 片段,但它不会增加发送方绑定,也不会完成领域授权。
ssl_verify 默认为 true,用于验证身份提供商的 TLS 证书。设为 false 会跳过验证并削弱 Discovery/Introspection 信任边界;不要用 false 路径规避证书部署问题。已验证 Token 缺少任一 required_scopes 时会返回 403,无效 Bearer Token 则触发认证失败;应分别测试这两条路径。
claim_validator.audience.required 和 claim_validator.audience.match_with_client_id 均默认为 false。两者都保持 false 时,这项 Audience 检查既不要求 Token 包含 aud,也不会把它与插件的 client_id 比较。把 required 设为 true 会让 aud 成为必需 Claim;把 match_with_client_id 设为 true 同样会要求该 Claim 存在,并要求至少一个 Audience 值等于客户端 ID。上面的片段同时开启两项检查,是因为 financial-resource-server 代表其预期资源 Audience。若授权服务器采用不同的 Audience 标识,应按该契约配置匹配策略,而不是照抄此值。
上游 TLS 与 OIDC Discovery 或 Introspection 是两条不同连接。APISIX Upstream 的 scheme 默认为 http,因此本示例明确选择 https;tls.verify: true 会根据配置的 CA 信任验证上游证书。这项按 Upstream 验证证书的能力要求 APISIX-Runtime,使用前必须确认目标构建。若不设置 tls.verify,APISIX 会遵循 NGINX 验证配置,而该配置通常关闭;设为 false 则明确关闭验证。这里的 pass_host: node 会使用所选节点主机名进行证书名称验证。应分别测试有效连接,以及证书不受信任或主机名不匹配时的预期失败。
如果部署要求使用 mTLS 或 DPoP 绑定的访问令牌,就要端到端验证该能力。不能仅凭 bearer_only、证书 Subject 请求头或已解码 Token Claim 推断调用方完成了密钥持有证明。
上线前定义依赖故障行为
| 依赖故障 | 保守行为 | 偏可用性行为及风险 |
|---|---|---|
| 授权服务器元数据或 JWKS 不可用 | 使用有边界且仍有效的缓存,过期后拒绝 | 接受无法验证的 Token 会越过身份边界 |
| Introspection 不可用 | 拒绝需要实时 Introspection 的请求 | 缓存 Active 状态会延长撤销暴露窗口 |
| 授权同意/策略服务不可用 | 拒绝受影响的操作 | 陈旧策略可能允许已撤销操作 |
| 欺诈服务不可用 | 按产品文档进入挂起或拒绝路径 | 绕过可能造成资金损失;网关不能自行发明决策 |
| 审计接收端不可用 | 使用有界存储缓冲,或拒绝必须持久留证的操作 | 丢失事件会破坏重建与对账 |
不同操作可以采用不同选择。余额查询与资金转账不必共享同一种故障策略。应在路由旁记录决策,并演练缺失、缓慢、陈旧、恢复和部分提交路径。
保持幂等与证据完整
金融命令通常使用 POST,可能产生不可逆影响。网关可以要求幂等键并拒绝格式错误的请求,但领域服务必须把该键与已认证主体、规范化请求和持久结果原子关联起来。仅靠网关缓存无法证明账本是否已提交。
至少记录:时间、已认证客户端与主体引用、路由、策略版本、Token Issuer 与 Audience、发送方绑定结果、请求关联 ID、幂等键哈希、网关决策、领域结果引用和证据完整性元数据。尽量减少敏感值;保存引用,而不是完整 Token、账户号码或请求正文。
验证清单
- 网关是否验证 Issuer、Audience、Token 有效期、所需 Scope 与选定的发送方绑定机制?
- 客户端证书属性是否只有在 TLS 验证成功后才会被使用?
- 一个客户端的 Token 或证明能否被另一条连接重放?
- 路由访问是否与账户和交易授权明确区分?
- JWKS、Introspection、授权同意、欺诈、配额或审计服务缓慢或缺失时会发生什么?
- POST 重试是否由领域服务持久幂等能力提供保障?
- 在不存储机密信息的前提下,证据能否把网关决策与持久领域结果关联起来?
- 策略与证书轮换是否在到期前经过测试?
常见问题
mTLS 能否取代 OAuth?
不能。mTLS 可以认证客户端并把 Token 约束到证书;OAuth 仍负责传递授权上下文,而领域服务仍需授权具体资源与操作。
网关能否让支付操作具备幂等性?
不能单独完成。网关可以要求并转发幂等键,但提交支付的服务必须原子存储该键与结果。
网关审计事件成功是否证明资金已经转移?
不能。它只能证明网关的观测结果。金融状态变更应由账本或记录系统证明。
后续步骤
将本架构与网关 mTLS 运维、细粒度授权边界和访问日志审计证据结合起来。
