排查线上问题时,最常见的动作就是把一段接口响应复制出来格式化。可这段数据里往往带着访问令牌、用户邮箱、手机号甚至订单金额。把它贴进一个不明来源的在线格式化网站,等于把这些信息交给了陌生人的服务器。本文介绍一套在浏览器本地完成格式化、脱敏、对比和验证的流程,并教你自己验证“确实没有上传”。
先搞清楚:风险到底在哪里
多数在线工具的实现方式分两类:一类把输入发送到服务器,由服务器返回格式化结果;另一类在浏览器里用 JavaScript 直接处理。前者的风险是显而易见的:你的数据会进入对方的访问日志、错误日志甚至数据库,保存多久、谁能看到你都不知道。后者则不会把内容发送出去,但仍然有几个容易忽略的泄漏面。
| 泄漏面 | 会发生什么 | 应对 |
|---|---|---|
| 服务端处理型工具 | 输入内容出现在对方服务器的请求体和日志里 | 敏感数据不要用,或改用本地命令行(如 jq) |
| 浏览器扩展 | 有“读取所有网站数据”权限的扩展可以看到页面内容 | 用无扩展的隐私窗口,或先脱敏 |
| 剪贴板历史 | 系统或第三方剪贴板工具会保留你复制过的令牌 | 处理完清空剪贴板历史 |
| 屏幕共享与录屏 | 会议中把令牌显示在屏幕上 | 先脱敏,再共享 |
| 页面里的第三方脚本 | 统计、广告类脚本与你的数据无关,但属于页面的信任边界 | 用 Network 面板确认输入没有被发出;仍应先脱敏 |
一套可重复的本地处理流程
- 复制样本前先确认来源:只拿完成任务所需的最小片段,而不是整个响应。
- 粘贴到 JSON 格式化页面,输入内容约 300 毫秒后自动格式化,右侧得到可折叠的树形视图。
- 用 JSONPath 页面找出所有敏感字段的位置,如 $..token、$..password。
- 在树形视图里删除不需要的节点,或在输入框里把值替换成占位符。
- 用 JSON 对比页面比较脱敏前后两份内容,确认只改了预期的字段。
- 复制或下载结果后,清空页面上的输入并关闭标签页。
实战:脱敏一份接口响应
下面是一份典型的登录响应样本(内容为虚构):
{
"code": 0,
"data": {
"user": {
"id": 88231,
"name": "Li Wei",
"email": "liwei@example.com",
"phone": "13800138000"
},
"auth": {
"accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI4ODIzMSJ9.abc123",
"refreshToken": "r_9f2b7c1d",
"expiresIn": 3600
},
"orders": [
{ "id": "A-1001", "amount": 607.5, "card": "4111111111111111" }
]
}
}第一步:用 JSONPath 找全敏感字段
人眼容易漏掉深层字段。在 JSONPath 页面分别查询,可以得到所有匹配项:
$..accessToken → ["eyJhbGciOiJIUzI1NiJ9..."]
$..refreshToken → ["r_9f2b7c1d"]
$..email → ["liwei@example.com"]
$..card → ["4111111111111111"]$.. 表示递归下降,会在任意层级匹配同名字段。把它作为“检查清单”,每个字段都要有处理结论:删除、替换为占位符、或保留。
第二步:删除或替换
树形视图的每个节点都可以删除,适合直接去掉整个 auth 对象。需要保留字段结构、只隐藏值的场景(比如要给同事复现解析问题),则在输入框里把值改成占位符:
{
"code": 0,
"data": {
"user": {
"id": 0,
"name": "REDACTED",
"email": "user@example.test",
"phone": "00000000000"
},
"orders": [
{ "id": "A-0000", "amount": 607.5, "card": "REDACTED" }
]
}
}保留 amount 是因为问题可能与金额精度有关;删掉 auth 整个对象是因为本次排查与鉴权无关。“保留什么”应由排查目标决定,而不是机械地全部抹掉。
第三步:对比确认
把原始数据放左边、脱敏结果放右边,在 JSON 对比页面查看:应当只出现 changed 和 removed,不应出现意外的 added。数组是按下标比较的,如果删除了数组里的某个元素,后面的元素会显示为 changed,这是正常现象。这一步的价值在于证明:你没有顺手改坏结构字段。
自己验证“没有上传”:用 Network 面板
不要只相信网页上的说明,验证方法很简单:
- 打开浏览器开发者工具,切到 Network(网络)面板,点击清空按钮。
- 在页面里粘贴一段带有明显标记的内容,比如 {"probe":"UNIQUE-STRING-123"},并点击格式化。
- 观察面板中是否出现新的请求。用搜索框搜索你的标记字符串,查看所有请求的请求体和 URL。
- 正常情况下不应有任何请求携带你的内容。如果出现请求,查看它的目标域名和载荷。
更严格的做法是:先加载页面,再断开网络,然后继续操作。如果格式化仍然可用,说明处理确实发生在本地。需要提醒的是,页面本身仍可能加载统计、广告类脚本,它们会产生与你的 JSON 无关的请求;判断标准是你的内容有没有出现在任何请求里。
Network 面板里还有一个小技巧:勾选“保留日志”,再切换到你用的其他工具页面重复同样的测试。这样可以一次性比较多个工具的行为,避免只验证了其中一个。凡是会让你粘贴敏感内容的页面,都值得花一分钟做这个检查,这比阅读隐私声明可靠得多。
几个容易被忽视的细节
- 分享链接里不要带数据:不要把 JSON 拼进 URL 参数分享,URL 会被浏览器历史、代理和日志记录。
- 截图同样会泄漏:树形视图里展开的节点就是你的数据,截图前折叠或先脱敏。
- “删除节点”只改变页面中的结果,不会影响原始输入,除非你把输出回填。要确保最终分享的是脱敏后的版本,而不是原始输入框里的内容。
- 令牌即使看起来“过期了”也要处理:很多系统的刷新令牌有效期长于访问令牌,遗留的 refreshToken 比 accessToken 危险得多。
- 脱敏要覆盖 key 和 value:有的系统会把用户名直接放在 key 里,如 {"user_liwei": {...}}。
四种脱敏方式怎么选
“脱敏”不是只有删除一种做法。不同方式保留的信息量不同,适用的场景也不同,选错方式要么让样本失去复现价值,要么留下泄漏风险。
| 方式 | 做法 | 优点 | 风险和限制 |
|---|---|---|---|
| 删除 | 直接去掉整个字段或对象 | 最彻底,不会残留 | 结构变了,可能无法复现与该字段相关的问题 |
| 固定占位符 | 把值换成 REDACTED 之类的常量 | 保留字段结构,改动一目了然 | 类型和长度信息丢失,校验长度的逻辑无法复现 |
| 同类型假值 | 换成格式相同的虚构数据,如 user@example.test | 保留类型和格式,适合复现解析问题 | 要确保假值不指向真实对象,例如不要用真实存在的域名 |
| 单向哈希 | 用哈希值替换,使相同原值得到相同结果 | 能保留“两处是同一个值”的关系 | 手机号、短 ID 这类取值空间小的数据可以被穷举还原,不适合隐私要求高的场景 |
一个实用的经验:先问“这个字段与问题有关吗”。无关的一律删除;有关但敏感的,用同类型假值;只有当“相同值之间的关系”本身是问题的关键,才考虑哈希。
把样本贴进工单:一个可以直接套用的格式
脱敏完成后,贴给同事或工单系统的内容也要有统一的格式,否则别人还得反复追问。建议至少包含下面几项:
- 来源:接口路径、环境(测试或生产)和获取时间,不要附带令牌或完整请求头。
- 期望与实际:你期望得到什么,实际得到了什么,用 JSON 对比的结果表述最清晰。
- 脱敏说明:哪些字段被删除,哪些被替换成了占位符,避免别人误以为数据本来就长这样。
- 最小样本:只保留复现问题所需的字段和数组元素,而不是完整响应。
最小样本还有一个好处:体量小,格式化后不需要滚动,评审的人能一眼看完。
这种做法的局限:什么时候不该只靠它
- 浏览器本地处理解决的是“不发给第三方服务器”,不能替代公司的数据合规要求。如果数据受法规或合同约束,请遵循内部流程,必要时使用公司批准的内网工具。
- 超大文件(几十 MB 以上)会让浏览器变慢,用 jq 等命令行工具在本机处理更合适。
- 需要批量、自动脱敏上千份文件:网页是人工操作的,应当写脚本,并让脚本里的脱敏规则可以被测试。
- 手工替换难以保证完整:对合规要求高的场景,应当用白名单思路,只保留确认安全的字段,而不是找出所有敏感字段并删除。