rea-reverse

HAR 文件查看与分析:读懂抓包、归纳接口,安全地分享给别人

基于 REA 6.4.0更新于 约 8 分钟读完
本页目录

客服让你“导一份 HAR 文件发过来”。你在 DevTools 里点了导出,手上就多了一个 JSON 文件:页面发出的每个请求、收到的每个响应都在里面,很可能还有你的会话 Cookie 和 Bearer token。本文就讲这个文件:各浏览器怎么导出、怎么看、怎么把几百条记录归纳成一张接口清单,以及发给任何人之前要检查什么。

会用到两个工具。本站的 HAR 分析器 在浏览器里运行,把抓包变成一份脱敏的接口摘要。REA(morluto 的开源项目)提供 inspect-web-network-capture,让 AI agent 逐条读取同一份 HAR,而且不会访问录制里的任何 URL。

适合谁读: 需要根据抓包排查 Web 应用问题、或者要把抓包交给别人的开发、测试和技术支持人员。

你会学到:

  1. 在 Chrome、Edge、Firefox、Safari 里导出 HAR
  2. 找到 HAR 里的敏感位置:请求头、Cookie、查询串和请求/响应体
  3. 按接口归纳 HAR,找出慢请求和错误码
  4. 决定分享什么,弄清两个工具的脱敏各管什么、不管什么
  5. 用 REA 6.4.0 让 agent 读取 HAR

只抓你有权记录的流量: 自己的应用、测试账号,或你获得授权测试的系统。HAR 里可能有他人的个人数据。请先阅读 REA 的 DISCLAIMER.md。

HAR 文件是什么

HAR(HTTP Archive)是一种 JSON 格式。顶层是 log,下面有 version(通常是 "1.2")、creator(写出文件的浏览器)和 entries。每个 entry 是一对请求和响应:

  • request:方法、带查询串的 URL、请求头、Cookie,以及请求体 postData
  • response:状态码、响应头、Cookie,以及 content,响应体放在 text 里(有时是 base64)
  • time 和 timings:请求耗时,分成 wait(首字节时间)等几个阶段

因为响应体通常也在里面,HAR 远不只是一串 URL。这正是它适合排查问题的原因,也是需要小心对待它的原因。

第 1 步:从浏览器导出 HAR

不管哪个浏览器,都要在复现问题之前打开开发者工具。Network 面板只在打开期间记录。

Chrome 和 Edge(Chromium 内核):

  1. 按 F12 打开 DevTools,切到 Network,勾选 Preserve log,避免页面跳转时清空列表。
  2. 复现问题。
  3. 点 Network 工具栏上的下载图标,选择 Export HAR (sanitized)…。

从 Chrome 130 开始,默认导出不包含 Cookie、Set-Cookie 和 Authorization 请求头。要导出它们,必须打开 Settings > Preferences > Network > Allow to generate HAR with sensitive data。提交工单时,几乎总是选脱敏版就够了。

Firefox: 打开开发者工具,切到 Network,页面会跳转的话打开 Persist Logs,复现问题后在请求列表上右键,选 Save All As HAR。Firefox 没有 Chrome 那一步脱敏,请当作它什么都包含。

Safari: 先在 Safari 设置里打开开发菜单(高级 > 显示网页开发者功能),打开 Web 检查器,切到 网络,复现问题后用 导出 保存 .har 文件。同样按未脱敏处理。

抓包越短越好。 在你关心的操作之前开始记录,操作完马上停止。短的抓包更好读,包含的个人数据也更少。

第 2 步:知道秘密藏在哪里

在归纳或分享 HAR 之前,先弄清敏感值通常在哪:

位置 常见内容 Chrome 脱敏导出会去掉吗?
Authorization 请求头 Bearer token、Basic 凭证 会
Cookie / Set-Cookie 头和 cookies 数组 会话 ID 会
其他请求头,如 X-Api-Key API key 不会
URL 查询串 ?token=、?api_key=、签名 URL 参数 不会
postData.text 登录表单里的密码、个人信息 不会
response.content.text 服务器返回的任何内容,包括用户资料 不会

最容易漏掉的是后三行。Chrome 脱敏导出的文件里,查询串中仍可能有 API key,响应体里仍可能有完整的用户资料。

第 3 步:按接口归纳 HAR

400 条记录的 HAR 用文本编辑器很难看。通常你想要的是一张接口清单:每个接口调用了几次、返回了哪些状态码、耗时多少。打开 HAR 分析器,把文件拖进去即可。文件在当前标签页的 Web Worker 里解析,不会上传。

为了展示真实结果,我们给一个演示用的笔记应用 notes.example.com 构造了一份小 HAR,共 7 条:两次读取笔记、一次新建笔记、一次返回 500 的搜索、一次 GraphQL 查询,以及两个脚本,其中一个来自第三方域名。部分请求带着 JWT Bearer token 和会话 Cookie,搜索 URL 里带着 api_key=test-key-123。下面是分析器导出的 JSON 片段:

{
  "summary": {
    "exchanges": 7,
    "endpoints": 6,
    "firstParty": "example.com",
    "thirdPartyRatio": 0.143
  },
  "endpoints": [
    {
      "host": "notes.example.com",
      "method": "GET",
      "path": "/api/notes/{id}",
      "count": 2,
      "status": { "200": 2 },
      "credentials": [
        { "where": "header", "name": "authorization", "value": "[REDACTED]",
          "length": 60, "scheme": "Bearer", "jwt": true },
        { "where": "cookie", "name": "sid", "value": "[REDACTED]", "length": 20 }
      ],
      "maxMs": 2400,
      "avgMs": 1242.5,
      "resShape": { "object": { "id": "number", "title": "string",
        "tags": { "array": "string" }, "archived": "boolean|null" } }
    },
    {
      "host": "notes.example.com",
      "method": "GET",
      "path": "/api/search",
      "status": { "500": 1 },
      "query": ["api_key", "q"],
      "credentials": [
        { "where": "query", "name": "api_key", "value": "[REDACTED]", "length": 12 }
      ],
      "maxMs": 310
    }
  ]
}

怎么读:

  • 路径模板把重复调用合并。 /api/notes/41 和 /api/notes/42 合成了一行 /api/notes/{id},count: 2。纯数字、UUID、JWT、日期、长十六进制串、邮箱和类似 token 的随机串都会换成占位符;order-12345 这样的 slug 保持原样。
  • 把 maxMs 和 avgMs 放在一起看,就能找到慢请求。 平均 1242.5 ms 掩盖了实情:两次读取里有一次花了 2400 ms。某个接口的最大值远高于平均值时,先查它。
  • status 按接口统计错误。 搜索接口返回了 500。状态码 0 表示请求没有收到响应,例如被拦截或取消。
  • resShape 只描述结构,不含数据。 能看出 archived 有时是布尔值、有时是 null,前端 bug 常常就出在这种差异上。
  • GraphQL 请求按操作拆开。 演示里的 /graphql 单独成为一个接口,"kind": "graphql"、"operation": "query Me",查询文本和变量都没有保留。

我们还在完整导出里搜索了演示文件中的每个秘密:JWT、Cookie 值、test-key-123、搜索词和笔记正文,一个都没找到。分析器从不把请求头、Cookie、查询参数或请求/响应体的值写进报告,只保留名称、类型、次数和最长值的长度。

第 4 步:决定分享什么

分析器不会生成一份清理过的 HAR,它生成的是摘要。所以你有三种选择,按安全程度排序:

  1. 分享分析器导出的 JSON。 里面没有任何值,只有域名、路径模板、名称、类型、次数和耗时,但会带上你打开的文件名。回答“哪个接口出错、有多慢”已经够用。
  2. 分享浏览器的脱敏导出。 用 Chrome 或 Edge 的 Export HAR (sanitized),然后按下面的清单自己检查查询串里的 API key 和请求/响应体里的个人数据。
  3. 只有对方确实需要完整的头和正文时,才分享完整 HAR,并通过公司认可的渠道发送。发完之后退出这个测试会话,让里面的 token 失效。

分享前检查清单:

  • 在文件里搜索 token、key、secret、password、session 和 eyJ(大多数 JWT 的开头)。
  • 搜索你自己的邮箱、姓名和手机号。
  • 检查登录、注册请求的 postData.text。
  • 看看抓包里有没有其他标签页或无关网站的请求。
  • 尽量用测试账号。真实账号的 token 在过期或退出登录之前一直有效。

分析器的凭证规则覆盖哪些: 名为 authorization、proxy-authorization、cookie、set-cookie、x-api-key 的请求头;名称里含 token、secret、password、session、key、auth、signature、credential 的请求头或查询参数;以及值是 JWT 的任何请求头或查询参数。这些会作为凭证按名称列出。其他值同样会被丢弃,因为报告根本不存值。分析器做不到的是判断某个正文字段里是不是个人数据,它只能告诉你 title 字段是字符串。

第 5 步:用 REA 让 AI agent 读 HAR

摘要告诉你该看哪一条请求。要看这条请求真实的头和正文,或者让 agent 把请求和前端代码对照,就用 REA 的 inspect-web-network-capture。它不需要浏览器,也不需要额外的分析引擎。安装方法见 REA MCP 安装指南。

rea inspect-web-network-capture /absolute/path/notes-demo.har har --record 1 --json

--record 接受从 0 开始的条目序号,可以重复写多次;不写就读取全部条目。下面是 REA 6.4.0 对演示文件第 1 条返回结果的一部分:

"records": [
  {
    "ordinal": 1,
    "location": { "kind": "json-pointer", "pointer": "/log/entries/1" },
    "reported": {
      "request": {
        "method": "GET",
        "url": "https://notes.example.com/api/notes/41",
        "headers": [
          { "name": "authorization", "value": null },
          { "name": "cookie", "value": null }
        ]
      },
      "response": {
        "status": 200,
        "content": {
          "mimeType": "application/json",
          "text": "{\"id\":41,\"title\":\"a\",\"tags\":[\"x\"],\"archived\":false}"
        }
      }
    },
    "redactions": [
      { "pointer": "/request/headers/0/value", "reason": "transport-credential" },
      { "pointer": "/request/headers/1/value", "reason": "transport-credential" }
    ]
  }
]

它和分析器是两类工具。REA 按浏览器写出的原样保留记录,包括响应体,并记录 Evidence ID 和文件的 SHA-256,agent 可以准确说明某个事实来自哪个文件的哪一条。它只去掉已知的传输凭证:Authorization、Proxy-Authorization、Cookie、Set-Cookie 请求头的值,Cookie 值,以及 URL 里嵌入的用户名和密码。

其余内容都会保留。我们读取第 4 条(那条失败的搜索)时,URL 原样返回 https://notes.example.com/api/search?q=invoice&api_key=test-key-123,redactions 是空列表。要排除这类值,需要显式声明:

rea inspect-web-network-capture /absolute/path/notes-demo.har har \
  --record 4 --sensitive-value 'test-key-123' --json

加上这个参数后,REA 6.4.0 把整个 url 字段换成了 null,并记录 {"pointer": "/request/url", "reason": "explicit-sensitive-value"}。输出里任何地方都找不到这个 key,Evidence 参数里也只记 "sensitive_value_count": 1,不记值本身。注意它丢掉的是整个字段而不是匹配的那一段,所以这条记录的 URL 其余部分也看不到了。

通过 MCP 调用时,agent 使用 inspect_web_network_capture,传入 capture_path、format: "har",可选 record_ordinals 和 sensitive_values。提示词可以这样写:

用 REA 读取 /absolute/path/notes-demo.har。找出失败或耗时超过一秒的请求,
给我看它们的请求和响应,并注明每条的 record ordinal。把 test-key-123 当作敏感值。

REA 6.4.0 在这里做不到的事: 它只接受 HAR 1.2 和 mitmproxy 原生抓包,后者需要 Linux 上的 mitmdump 12.2.3。它不读 Fiddler 的 .saz 文件(本站分析器可以读)。它没有针对 HAR 的接口归纳视图,归纳请用分析器的摘要。输入上限 32 MiB。它从不发请求,用它自己限制说明里的话说:“Recorded URLs are never fetched”。

常见问题和排错

分析器提示 JSON 不是 HAR 1.2 格式。 文件缺少 log.entries,或者某条记录没有请求方法、URL 或响应状态码。请从浏览器重新导出,不要手工改。

明明需要登录的接口,凭证列表却是空的。 你的 HAR 很可能来自 Chrome 的脱敏导出,Authorization 和 Cookie 在分析器看到之前就被删掉了。用于分享这没问题。要审计哪些接口带了凭证,就用包含敏感数据的导出,在本地分析,用完删掉。

REA 拒绝读取文件。 REA 只接受 HAR 1.2,会拒绝有重复 JSON 键的文件,输入上限 32 MiB。请重新导出一份只覆盖目标操作的短抓包。

同一个接口出现了两次。 路径里有某一段被占位规则当成普通单词,例如 order-12345。每一行本身是对的,只是没有合并。

FAQ

HAR 文件可以直接发给客服吗?

默认不行。Chrome 或 Edge 的脱敏导出去掉了 Cookie 和 Authorization,但查询串和正文还在。按上面的清单检查一遍;如果摘要就能回答问题,直接发分析器的摘要。

HAR 分析器会上传我的文件吗?

不会。它在 Web Worker 里运行,Worker 的内容安全策略禁止任何网络请求。工具页说明了怎么用浏览器的 Network 面板或断网来自己验证。

不用任何工具能看 HAR 吗?

可以,它就是 JSON。jq '.log.entries[] | [.request.method, .request.url, .response.status, .time]' file.har 就能得到一张简单的表。不过要分享结果,还是需要路径模板和脱敏。

这篇和“追踪 API 调用到代码”有什么区别?

本文讲 HAR 文件本身。要从一个请求找到发出它的 JavaScript,请看 用 REA 追踪网站 API 调用。

下一步