如果你也做 SaaS 项目,你一定遇到过这种情况:
- 同一个接口在租户 A 正常,租户 B 却 403
- 不同租户下功能开关表现不一致,前端不知道错在哪
- 测试环境与预发环境行为不一致,无法定位原因
- 客户提交问题但无法复现,只有截图和“猜测”
这些问题,日志往往无解。最靠谱的做法,是直接抓包,看看请求里到底传了啥、返回了啥。
为什么抓包在 SaaS 项目里特别重要?
- 每个租户 Header 中都有不同的 token、tenantId、roleId
- 功能开关与配置在请求 header 中动态注入
- 版本差异可能影响响应字段结构
- 权限校验问题必须抓到实际请求才能验证
多租户调试推荐工具组合
| 工具 | 用途 | 特点 |
|---|---|---|
| Charles | 多租户请求抓取与响应对比 | 方便观察 header 和响应内容差异 |
| Postman | 复现多个 token 请求 | 适合手动参数控制 + 环境变量切换 |
| mitmproxy | 批量模拟多租户请求 | 支持构造租户 ID、角色自动循环 |
| DevTools | 快速看 Cookie/token 注入是否正确 | 配合 Charles 核对 cookie 状态 |
Charles 中文站:charlesproxy.net/
场景一:租户 A 能访问,租户 B 被拒绝
我们在调试一个财务模块时,发现租户 A 能正常拉账单数据,而租户 B 一直返回 403。
用 Charles 抓取两个请求,发现 header 中的 X-Role-Permission 字段为空,而 A 的请求中该字段为 "view-bill": true。
进一步查后端发现租户 B 配置中心缺了该功能开关。
场景二:功能开关未同步,影响前端逻辑判断
前端页面根据响应体中的 "features" 字段渲染不同模块。有一次客户反馈“怎么没有报表页”,但前端渲染逻辑正常。
用 Charles 抓请求,发现该租户返回:
json复制编辑"features": {
"report_module": false
}
才发现是开关未同步,配置平台设成了 false。无须改代码,只需后台同步即可。
mitmproxy 实战脚本:验证多租户行为一致性
我写过一个脚本,自动从配置文件中读取 20 个租户的 token 和 tenantId,然后自动请求同一个 API,抓取响应中的 "enabledFeatures" 字段。
for tenant in tenant_list:
request.headers["X-Tenant-ID"] = tenant["id"]
request.headers["Authorization"] = f"Bearer {tenant['token']}"
replay(request)
对比响应,发现有两个租户误配置了过期字段,影响老版本前端逻辑渲染。
抓包在多租户项目中的高频价值
| 应用场景 | 抓包工具如何帮你 |
|---|---|
| 多租户权限不一致 | Charles 查看 token + tenantId + 权限字段 |
| 功能开关不同步 | 抓响应体中的 "features" 字段差异 |
| 环境行为不一致 | 用 Charles 对比同一请求在不同域名的响应 |
| 客户反馈无操作日志 | 教客户或测试抓包发 .chls 文件还原过程 |
| 请求调试逻辑太复杂 | mitmproxy 编写请求生成器模拟多场景 |
小结:多租户环境,猜配置不如抓数据
别再靠问配置中心是不是配错、前端是不是没判断,直接抓一次包、对一次字段,你就能一眼看出差异在哪。
抓包不是“开发临时排错工具”,它是SaaS 系统中识别行为差异的唯一真相源。
如果你参与多租户平台的调试或运维,建议所有团队成员都掌握抓包操作。 起步工具推荐:charlesproxy.net/