
1. 从一次接口没报错但页面挂了的现场说起后端同学把日志翻了三遍接口返回 200监控大盘一片绿前端同学把网络面板打开也确实看到请求发出去了只是响应体里躺着一行系统繁忙请稍后重试。这种场面做久了都熟三方各说各话因为每个人看的都是自己那一层的证据。真正能把这条链路拉直的动作只有一个——抓包。抓包这件事说白了就是把网卡或代理上流过的字节流截下来再按协议规则还原成人类能读的请求与响应。它解决的核心问题不是接口通不通而是实际发出去的报文究竟长什么样。浏览器调试面板能看到的是浏览器愿意告诉你的那部分抓包看到的是 TCP 连接上真实跑过去的东西包括你没意识到的重定向、多打的一次预检请求、被客户端偷偷加上的请求头、被网关改写的 Host。对做接口测试的人来说抓包还有个更实际的价值它是最快的用例来源。与其对着接口文档猜参数格式不如让真实业务跑一遍把报文原样捞下来去掉噪声就是一条可回归的用例。文档会撒谎或者滞后三个月线上跑过的报文不会。这篇内容面向三类人刚接手接口测试、还不知道从哪下手的同学做了几年功能测试、想补上协议这一课的同学以及被 App、小程序、模拟器抓包折磨过、证书装了三遍还是 unknown 的同学。我尽量把每一步的为什么讲清楚而不是丢一堆截图让你照着点。1.1 代理层截获和网卡层嗅探是两码事新手最容易混的一点是把 Charles 和 Wireshark 当成同类工具实际上它们站的楼层完全不同。代理型工具Charles、Fiddler、mitmproxy、Reqable、Burp Suite 这一类的工作方式是你让客户端把流量主动发给它它扮演一个中间人把请求转发给真实服务器再把响应转回来。因为它是链路的合法参与方所以它能对 HTTPS 做解密——前提是客户端信任了它伪造的证书。它的产出是 HTTP 语义级别的可读报文方法、URL、Header、Body、状态码。网卡型工具Wireshark、tcpdump的工作方式是网卡进入混杂模式把经过的每一个帧都收下来。它不参与链路只是旁听。所以它对 HTTPS 无能为力——你只能看到 TLS 握手的记录、证书的元信息、加密后的密文长度。它擅长的是另一类问题TCP 三次握手为什么失败、有没有重传、DNS 解析花了多久、某个包的 TTL 是不是异常、局域网里有没有多余的广播。一句话区分要测接口用代理要查网络用嗅探。我见过太多人拿着 Wireshark 抓 HTTPS 接口包盯着密文问为什么解不开这不是工具不行是选错了楼层。1.2 什么时候必须上抓包什么时候不必有三种场景抓包基本是唯一解客户端行为不可控。App 做了代码混淆、请求体是二进制、部分参数由 SDK 内部生成你没法从前端代码里读出真实参数。这时候只能让 App 跑一遍看它到底发了什么。责任边界说不清。前端说传了后端说没收到网关说转发了。抓一次全链路谁的锅当场就定了。要复现一个偶发问题。崩溃日志里只有堆栈没有报文。抓包能把案发那一秒的请求完整留下来。反过来如果只是验证一个已知接口的入参出参Swagger 文档齐全直接打开 Postman 敲参数就行抓包纯属绕路。工具是用来省时间的不是用来证明自己会的。2. 工具选型Charles、Fiddler、Wireshark、tcpdump 各守哪个岗位选工具这件事我的原则是按问题的楼层选不按哪个火选。下面这张表是我这几年给团队新人做培训时用的版本基本能覆盖 90% 的日常场景。工具层级擅长明显短板适合谁Charles代理HTTP/HTTPS 解密、断点改包、Map Local、弱网模拟界面偏重长期抓大流量吃内存测试、客户端开发Fiddler Classic代理脚本扩展强、Windows 生态友好、SAZ 归档仅 WindowsHTTPS 配置略绕测试、后端mitmproxy代理命令行、Python 脚本化、可自动化无 GUI门槛高有开发能力的测试、运维Reqable代理抓包与调试合一HTTP/2、WebSocket 支持好生态较新插件少想少装几个工具的人Burp Suite代理安全测试、重放与爆破学习曲线陡非安全场景用不上安全测试Wireshark嗅探协议全、过滤表达式强大、可看 TCP 细节不能解 HTTPS 业务体网络、运维、客户端tcpdump嗅探服务器无图形界面必备、可长时间落盘纯命令行分析要导出到 Wireshark运维、后端2.1 代理型工具怎么挑Charles 还是 Fiddler如果只装一个我通常建议 Charles。原因不是它功能最多而是它把改包这件事做得最顺手Breakpoints可以在请求发出前拦下来改参数Map Local可以把某个接口的响应直接换成本地文件Rewrite能批量改写 Header 和 BodyThrottle能把网速压到 2G 水平看客户端的降级表现。这四个功能组合起来就能覆盖绝大多数异常场景测试的需求而这些场景往往是用例设计里最难手工构造的部分。Fiddler Classic 的优势在脚本。它的CustomRules.js可以在OnBeforeRequest、OnBeforeResponse里写任意逻辑比如自动给所有请求加时间戳、自动把某个响应体的金额字段改成随机值。做批量数据构造时Fiddler 比 Charles 省事。缺点是它死守 Windows 平台Mac 用户只能用 Fiddler Everywhere功能和体验都要打折。我的实际组合是日常调试用 Charles需要写脚本批量造数据时切 Fiddler团队协作用 Charles 的.chls会话文件导出它会自动带上请求时间线和完整报文比截图有说服力得多。2.2 Wireshark 和 tcpdump查网络通不通而不是接口对不对Wireshark 的正确打开方式是配合显示过滤器。几个我几乎每次都会用到的表达式tcp.port 443 ip.addr 10.20.30.40 # 只看某个服务端的 HTTPS tcp.flags.syn 1 tcp.flags.ack 0 # 只看建连请求快速判断谁在连谁 tcp.analysis.retransmission # 只看重传判断丢包 http.request.method POST # 明文 HTTP 场景下按方法过滤 dns.qry.name contains example # 看域名解析是否正常tcpdump 则更适合服务器侧。它常常是排查线上问题的唯一手段因为生产环境不会给你装图形界面。一条比较实用的长时间抓包命令是这样的# 抓 eth0 上 443 端口流量按 100MB 切文件最多保留 20 个最多约 2GB tcpdump -i eth0 -s 0 -w /data/cap/api_%Y%m%d_%H%M%S.pcap -C 100 -W 20 tcp port 443这里的-s 0表示抓完整包长不截断-C 100是单个文件到 100MB 就换下一个-W 20是环形缓冲最多留 20 个文件。环形缓冲这个参数特别重要——线上抓包最常见的翻车不是没抓到是把磁盘抓满了导致服务不可用。用环形缓冲旧文件自动被覆盖风险可控。提示抓包本身不改变流量走向但长期抓包会带来磁盘 IO 和 CPU 开销。生产环境务必加上文件大小和数量限制并在排查结束后立刻停掉。2.3 抓包与分析工具之间的交接实际工作流里工具不是二选一而是接力。我常用的链路是Charles 抓业务报文并导出 HARApifox 导入 HAR 生成接口定义Postman 或 JMeter 做回归遇到性能或连接层问题时用 Wireshark 复核 TCP 行为。HAR 是个很好用的中间格式主流代理工具都能导出Apifox、Apipost、Postman 也都能导入省掉了大量手工敲接口的时间。3. HTTPS 能被看懂的前提证书信任链上的每一个开关抓包最常见的挫败感来自这里流量抓到了但每条记录都显示unknown或者只看到 CONNECT 请求看不到具体的路径和响应体。这不是工具坏了是解密链路没打通。3.1 中间人代理解密的原理用快递代收点来类比服务器的证书是给域名签发的客户端连上代理后代理会现场伪造一张对应域名的证书发给客户端。客户端如果信任这张伪造证书就会把数据加密发给代理代理用自己的私钥解开看到明文再重新加密转发给真实服务器。问题在于客户端默认只信任权威 CA 签发的证书凭什么信任代理伪造的答案就是你把代理的根证书手动装进了客户端的信任库。装完之后代理签发的所有子证书客户端都会认。这也是为什么没有装证书就绝对解不开 HTTPS——这不是软件设置问题是密码学保证任何工具都绕不过去。同理如果某个 App 做了证书固定把服务端证书的公钥硬编码在包里即使你装了代理证书握手也会失败抓包记录里只会留下一句Client closed connection。这类情况属于客户端主动拒绝正规做法是找客户端同学要一份 debug 包而不是去想办法绕过它。3.2 证书装了三遍还是 unknown检查这几个点这个坑我踩过不止一次按下面顺序查基本都能定位只装了证书没开启信任。iOS 上装描述文件只是第一步还必须去设置 → 通用 → 关于本机 → 证书信任设置里把对应根证书的开关打开。这一步漏了表现就是证书列表里有它但抓包依然是 unknown。Android 7.0 之后的用户证书默认不被应用信任。系统从这一版开始把信任库拆成系统证书和用户证书应用默认只认系统库。所以同样是装在同一台手机上的证书浏览器能用App 却抓不到。正常解法是让客户端同学在测试包里配置networkSecurityConfig放行调试证书或者把构建类型设为 debug。证书下错了域名。手机浏览器里访问代理工具提供的证书下载地址时注意区分——有的是给当前机器用的有的是给移动端用的装错一份等于没装。客户端走了代理之外的通道。有些 App 在检测到代理设置后会切换到直连或者对特定域名使用 HTTP/3QUIC走 UDP 443。代理工具通常只接管 TCPUDP 流量会被直接放过去于是关键请求就这么消失在视野里。遇到这种情况可以临时在客户端侧关掉 QUIC 相关开关或者在抓包机上屏蔽 UDP 443。3.3 别把整台机器的流量都抓下来新手常见的另一个问题是打开抓包列表里刷出几千条记录全是系统更新、埋点上报、广告请求想找的那条接口淹没在里面。两个习惯能救命一是开白名单。在 Charles 的SSL Proxying Settings里只填你关心的域名比如api.example.com:443其他域名让它们以 CONNECT 形式过去就行。这样既减少噪音也降低抓包机的负担。二是先清空再复现。清空会话然后只做一个动作比如点一次提交订单列表里剩下的就基本是这一个动作引发的请求。这个习惯能让定位效率提升一个数量级尤其是定位一次点击触发多少个接口这类问题时。4. 手机端抓包实操从代理配置到第一个正常响应移动端抓包之所以让人头疼是因为多了手机和电脑之间的网络这一步以及手机上一堆和桌面端不同的信任规则。整个流程其实只有五步但每一步都有坑。4.1 让手机和抓包机看得见彼此第一步是网络可达。最稳的方式是让手机和电脑连同一个 WiFi然后确认电脑的局域网 IP在手机的 WiFi 设置里填手动代理主机名填电脑 IP端口填代理工具监听的端口Charles 默认 8888Fiddler 默认 8888。这里有几个高频故障电脑开了防火墙。表现是手机浏览器打不开任何网页代理工具里一条记录都没有。临时放行代理工具进程即可。端口被占。8888 是个热门端口很容易被其他程序抢占。代理工具启动时报端口占用就换一个比如 8899然后手机代理同步改。公司网络做了隔离。有些企业 WiFi 开启了客户端隔离同一网段下设备互不可见。这种情况用电脑开热点让手机连热点是最省事的绕法。代理开了但没生效。部分手机的 WiFi 代理设置对某些 App 无效尤其是有自己网络库的 App。可以先在手机浏览器访问一个明文 HTTP 页面确认代理链路通了再去看 App 的行为。4.2 安卓和 iOS 的信任差异决定了你能抓到什么前面提过Android 7 以后应用默认不信任用户证书这是移动端抓包失败的头号原因。判断方法很简单如果手机浏览器能抓到 HTTPS 明文但目标 App 全是 unknown基本就是这个原因。正规解法是让客户端出一个 debug 包里面配置好信任调试证书。iOS 的情况稍有不同系统层面只要你开了信任开关App 一般能抓到除非做了证书固定。但注意 iOS 的代理是全局的一旦配好所有 App 的流量都会经过代理包括一些后台同步流量列表会很吵。用域名白名单控制。还有一个细节部分 App 会在启动时读取系统代理设置如果发现处于代理环境会主动降级或者走长连接。表现是启动瞬间有几条请求之后就没有了。这时候可以试试在 App 启动前就配好代理并清空列表观察启动阶段的流量峰值。4.3 小程序和模拟器的特殊之处小程序的请求走的是宿主 App微信、支付宝等的网络层抓包方式和普通 App 一样但有一点要注意小程序对请求域名有白名单限制且经常走 HTTP/2 或长连接。用支持 HTTP/2 的代理工具Reqable、Charles 较新版本能看到更完整的内容老版本工具可能只显示一条 CONNECT。模拟器这边常见问题是模拟器的网络出口和宿主机不同。以常见的安卓模拟器为例需要先确认模拟器能不能访问宿主机的局域网 IP很多时候模拟器内部有自己的虚拟网络127.0.0.1指向的是模拟器自己而不是宿主机。解决办法是用宿主机的局域网 IP或者用模拟器提供的宿主机映射地址。5. 把抓到的请求变成能回归的接口测试用例抓到包只是开始真正的价值在于把这些报文变成一套能重复执行、能进 CI 的测试用例。这一步做得好不好决定了你的接口测试是一次性截图交付还是可持续资产。5.1 从几百条会话里挑出主干我的做法是按业务动作分组每个动作只保留最小必要请求链。比如下单这个动作抓出来 12 条请求其中 8 条是埋点、图片、配置拉取真正影响业务结果的只有 4 条加购、查库存、下单、查订单状态。把这 4 条留下其余丢掉。整理成表之后长这样序号接口方法关键入参依赖前序断言点1/api/loginPOSTmobile, code无code0返回 token2/api/cart/addPOSTtoken, skuId, num1code0cartSize13/api/order/createPOSTtoken, skuId, addrId, sign1code0返回 orderNo4/api/order/detailGETtoken, orderNo3状态为待支付这张表看起来朴素但它是整个接口测试的骨架。评审时拿着它和产品、后端过一遍比看几十张截图高效得多。5.2 参数化与关联token、签名、时间戳抓包拿到的报文有个特点它带着当时的上下文。token 是那一刻的时间戳是那一刻的签名是根据那一刻的参数算出来的。直接把报文粘进 Postman 能跑通一次第二天就 401 了。处理方式分三类可复制的动态值token、sessionId、orderNo用关联解决即从前一个响应里提取注入到后续请求。Postman 里是在 Tests 标签写提取脚本// 从登录响应中提取 token写入环境变量 const res pm.response.json(); pm.test(登录成功, function () { pm.expect(res.code).to.eql(0); }); pm.environment.set(token, res.data.token); pm.environment.set(uid, res.data.userId);后续请求的 Header 里写Authorization: Bearer {{token}}即可自动引用。需要计算的签名这类是自动化的真正门槛。常见做法是签名算法固定但密钥在客户端。如果测试环境提供了固定的测试密钥可以把它配置进环境变量用 pre-request script 复现签名逻辑如果没有只能让后端提供关闭验签的开关仅限测试环境且必须有访问控制。不要在测试脚本里硬编码生产密钥这是红线。时间戳、随机数、序列号用脚本生成注意格式秒级还是毫秒级、有没有补零。这类参数出错时接口往往返回签名错误很容易误判成密钥问题实际只是时间戳差了几百毫秒。5.3 断言写什么决定了这套用例有没有价值只断言 HTTP 200 的用例价值接近零。我的断言分层是这样的协议层状态码、Content-Type 是否符合预期。业务层响应体的code/status字段是否为成功值关键字段是否非空。数据层金额计算是否正确、列表数量变化是否符合预期、订单状态是否按时序流转。结构层用 JSON Schema 校验字段类型和必填项防止后端悄悄删字段导致前端崩溃。性能层响应时间设一个宽松阈值比如 2 秒告警不追求精确只抓明显劣化。举个数据层断言的例子下单后查库存必须减一这个断言比接口返回成功有意义得多const body pm.response.json(); pm.test(库存扣减正确, function () { pm.expect(body.data.stock).to.eql(pm.environment.get(stockBefore) - 1); });5.4 Postman、Apifox、JMeter 三套落地方式的取舍维度PostmanApifox / ApipostJMeter上手成本低低中高导入 HAR 生成接口支持支持且更顺不支持直接导入接口文档一体弱强定义、Mock、测试一体无参数关联环境变量 脚本环境变量 脚本提取器 变量并发压测弱需 newman弱强线程组 监听器进 CInewman 命令行友好有 CLI命令行模式成熟我的实际分工是Apifox 管接口定义和日常调试团队共享一份定义改一处全员同步比各自维护 Postman 集合省心Postman 处理需要复杂脚本的用例JMeter 负责并发和稳定性验证。用 JMeter 做并发时线程数不要拍脑袋。举个实际算法如果要在 5 分钟内打出 3000 个请求平均 RPS 是 10考虑到响应波动和集合点线程数按目标RPS × 平均响应时间(秒)估算假设平均响应 0.3 秒那么10 × 0.3 3个线程就够。很多人一上来就开 500 个线程结果是被压测机自己的瓶颈拖垮数据毫无参考价值。6. 抓包与接口测试的高频故障排查链路这一节把前面零散提到的坑集中起来按症状 → 排查顺序 → 根因组织方便你直接对号入座。6.1 抓不到包从网络层一层层往上排排查顺序不要乱从下往上走最快物理与网络层手机和电脑在不在同一网段能不能 ping 通公司 WiFi 有没有开客户端隔离——不通就先解决这个后面都白搭。代理配置层代理工具的监听端口和手机里填的端口是否一致代理工具是否开启了允许外部连接有些工具默认只监听本机系统代理被绕过部分 App 忽略系统代理。判断方法是用浏览器验证代理链路本身通不通浏览器通、App 不通就是 App 层面的事。协议层被绕过流量走了 UDPHTTP/3或者长连接复用代理看不到。需要关掉客户端的 QUIC 或者用支持 UDP 转发的方案。本机自测的坑在电脑上用浏览器访问127.0.0.1上的服务时请求往往不走系统代理所以抓不到。这种情况改用局域网 IP 或者给浏览器单独装代理插件。6.2 抓到了但看不懂编码、二进制与长连接响应体是一堆乱码。先看Content-Encoding如果是gzip、br说明工具没自动解压。多数代理工具有解压选项勾上即可。Body 是二进制。头部有application/x-protobuf或application/octet-stream说明走的是自定义序列化协议。这种情况需要拿到.proto定义文件才能解析靠猜是猜不出来的。只有一条 CONNECT 就没了。多半是 HTTP/2 或者连接复用了。换用较新版本的抓包工具或者临时让客户端降级到 HTTP/1.1仅测试环境。WebSocket 抓不到内容。要选支持 WebSocket 帧查看的工具普通 HTTP 视图里只能看到握手那一次请求。请求体里带一串百分号编码。那是application/x-www-form-urlencoded抓包工具一般能自动解码展示手工复制时注意别把编码后的原样粘进脚本容易和脚本自身的转义撞车。6.3 抓包能跑通的请求脚本为什么发不出去这是接口测试里最经典的一类困惑报文一模一样地复制过来脚本却报 401 或签名错误。按下面几个方向查现象常见根因处理401 / 403token 过期、Header 名大小写或拼写差异、多了一个空格从响应里动态提取 token逐字段比对 Header签名错误参数顺序、编码方式、时间戳精度、多传了空值参数按签名文档逐字段核对注意空字符串参不参与计算400 参数错误抓包工具展示时做了美化实际是嵌套 JSON 字符串用原始视图复制 Body别用美化后的返回成功但数据不对少了客户端生成的头设备号、版本号、渠道号把这些头也纳入环境变量管理第一条能过第二条必挂接口有幂等或频率限制用例设计上区分数据准备与业务断言有一点必须强调抓包得到的 Header 不要无脑全抄。像Content-Length、Host、Connection这类由客户端库自动生成的抄进去反而容易冲突像x-forwarded-for、内部追踪号这类抄了可能触发风控。留必要的业务头其余交给工具生成。6.4 长时间抓包与数据留存的两个红线如果是排查偶发问题需要长时间挂机抓包一定注意磁盘。前面说的环形缓冲参数必须加同时监控磁盘水位。数据合规。抓下来的报文里包含真实用户手机号、地址、身份信息。这类文件不能提交到代码仓库不能随手通过聊天工具传用完及时清理。团队协作时建议对敏感字段做脱敏后再共享或者只共享请求结构而非完整报文。提示抓包只应用于你自己负责或已获得明确授权的系统和客户端。对不属于自己职责范围的流量做截获和分析既不合规也没有必要。7. 一些踩出来的经验证书固定这个问题我建议一开始就问清楚客户端同学这个包做没做固定而不是自己折腾半天证书安装。问一句省两小时这是我在移动端抓包上学到的最值钱的一条。另一个反直觉的体会是抓包工具用得越熟越容易过度依赖它。有些问题根本不用抓包就能定位比如接口返回结构变化导致前端渲染异常看一眼响应体就知道了比如超时问题先看服务端日志和监控曲线比抓包快得多。抓包是最后一道照妖镜不是第一把锤子。关于接口测试本身我最大的感受是用例的稳定性比覆盖面更重要。一套天天飘红、需要人肉重跑的环境很快就会没人看。宁可先做 20 条牢固的主干用例跑通 CI也别急着铺 200 条依赖手工造数据的脆弱用例。抓包帮你拿到真实的请求形态这是起点把它变成能自动跑、失败能说清原因、数据能自清理的用例才是这件事真正做完的标志。最后分享一个小习惯每次抓完包整理完接口我都会把那次会话导出成一个带日期的归档文件同时把关键接口的字段含义记在文档里。半年后再排查同样的接口这份归档能省掉重新抓一遍的全部时间——毕竟业务迭代之后抓包环境能不能顺利配起来有时候本身就是个问题。