2. 鉴权拦截链路全景:请求入口、网关层、服务层、数据层的鉴权拦截点与数据流
多租户 SaaS 的鉴权不是单点防御,而是一条贯穿请求全生命周期的拦截链路。任何一个层级出现鉴权缺失或配置错位,都可能导致租户数据泄露或越权操作。本章从请求入口到数据持久化层,逐层拆解鉴权拦截点与数据流转路径,为后续自动化测试的用例设计提供全景视图。
2.1 四层鉴权拦截模型
标准的多租户 SaaS 架构将鉴权拦截划分为四个层次:请求入口层、网关层、服务层、数据层。每一层承担不同的拦截职责,且拦截粒度逐层细化。
| 层级 | 拦截点 | 核心职责 | 典型技术实现 |
|---|---|---|---|
| 请求入口层 | CDN / WAF / 反向代理 | IP 白名单、DDoS 防护、TLS 终止、基础请求头校验 | CloudFront + WAF, Nginx, HAProxy |
| 网关层 | API Gateway / 统一接入网关 | Token 解析、租户识别、路由分发、限流熔断 | Kong, APISIX, Spring Cloud Gateway |
| 服务层 | 业务微服务 / BFF | RBAC/ABAC 权限校验、资源归属验证、租户上下文传递 | Spring Security, Casbin, OPA |
| 数据层 | 数据库 / 缓存 / 对象存储 | 行级安全策略、租户隔离视图、加密密钥隔离 | PostgreSQL RLS, Redis ACL, AWS KMS |
测试关注点:自动化测试需要覆盖每一层的正向通过场景和至少 3 种拒绝场景(无 Token、Token 过期、跨租户 Token)。仅测试网关层而忽略数据层,是 SaaS 鉴权测试最常见的遗漏。
2.2 鉴权拦截链路全景图
下图展示了从客户端请求到数据返回的完整鉴权拦截链路,包含每一层的核心拦截节点与数据流方向。
2.3 各层拦截点详细说明
2.3.1 请求入口层
- 拦截对象:所有进入 SaaS 公网 IP 的 HTTP/HTTPS 请求。
- 核心拦截逻辑:
- IP 白名单/黑名单:仅允许已知的办公出口 IP 或云服务商 IP 范围。
- TLS 终止与证书校验:拒绝无效证书或中间人攻击请求。
- 基础请求头校验:拒绝缺少 Host、User-Agent 等必要头的畸形请求。
- 测试要点:构造伪造 IP、过期证书、畸形请求头,验证入口层是否按预期拦截。
2.3.2 网关层
- 拦截对象:通过入口层校验的所有 API 请求。
- 核心拦截逻辑:
- Token 解析与验证:JWT 签名校验、过期时间检查、颁发者(iss)校验。
- 租户识别:从 Token 中提取 tenant_id,注入请求头 X-Tenant-ID。
- 路由分发:根据 tenant_id 或 API 路径将请求路由到对应服务实例。
- 限流与熔断:按租户级别进行速率限制,防止单个租户耗尽资源。
- 测试要点:篡改 Token 签名、使用过期 Token、跨租户 Token 访问、超限流阈值。
2.3.3 服务层
- 拦截对象:网关层放行的业务请求。
- 核心拦截逻辑:
- RBAC/ABAC 权限校验:验证当前用户是否拥有执行该操作的权限。
- 资源归属验证:确认请求操作的资源(如订单、文档)属于当前租户。
- 租户上下文传递:将 X-Tenant-ID 传递到数据访问层,确保隔离。
- 测试要点:低权限用户访问高权限接口、A 租户用户操作 B 租户资源 ID。
2.3.4 数据层
- 拦截对象:服务层发出的数据库查询、缓存读取、文件存储请求。
- 核心拦截逻辑:
- 行级安全策略(RLS):数据库根据当前会话的 tenant_id 自动过滤行数据。
- 缓存键隔离:Redis 键名前缀包含 tenant_id,防止跨租户缓存穿透。
- 加密密钥隔离:每个租户使用独立的 KMS 密钥加密敏感数据。
- 测试要点:直接连接数据库查询跨租户数据、使用错误租户的缓存键、尝试解密其他租户的加密字段。
常见陷阱:很多团队只测试了网关层的 Token 校验,忽略了服务层的资源归属验证和数据层的 RLS 策略。一旦网关层被绕过(如内部服务间调用未经过网关),数据层将成为最后一道防线——而这道防线往往最容易被遗漏测试。
2.4 鉴权数据流全景(请求与响应)
以下时序图展示了一次完整的多租户 API 请求中,鉴权数据在各层之间的传递与校验顺序。
2.5 自动化测试覆盖矩阵
基于上述四层拦截模型,自动化测试用例应覆盖以下矩阵。每个测试用例需明确标注其覆盖的层级与拦截点。
| 测试场景 | 入口层 | 网关层 | 服务层 | 数据层 | 预期结果 |
|---|---|---|---|---|---|
| 合法请求(完整 Token) | ✅ | ✅ | ✅ | ✅ | 200 OK,返回正确租户数据 |
| 无 Token 请求 | ✅ | ✅ | — | — | 401 Unauthorized |
| Token 过期 | — | ✅ | — | — | 401 Token Expired |
| Token 签名错误 | — | ✅ | — | — | 401 Invalid Signature |
| 跨租户 Token 访问 | — | ✅ | ✅ | ✅ | 403 Forbidden |
| 低权限用户操作高权限接口 | — | — | ✅ | — | 403 Forbidden |
| 直接查询数据库跨租户数据 | — | — | — | ✅ | 空结果集或错误 |
| IP 黑名单请求 | ✅ | — | — | — | 403 或连接拒绝 |
关键原则:每一层都应假设下层可能被绕过。因此,自动化测试不仅要测试“正常链路”,更要测试“单层绕过”场景——例如跳过网关直接调用服务 API、跳过服务层直接查询数据库。只有四层全部通过测试,才能确认鉴权拦截链路是完整的。