最近在调网页端采集接口时,又跟某红薯的 x-s 签名较上了劲。熟悉的朋友应该都知道,这个平台绝大多数 JSON 接口都要带上 x-s、x-t 这几个自定义 header,否则服务端直接不搭理你,要么 403,要么返回一段“验证码页面”。很多刚入坑的朋友第一次看到 x-s 就懵了,不知道这串东西怎么来的、去哪看算法、本地怎么调试。这篇文章我把整个分析过程和复盘记录整理出来,从抓包定位、调用栈回溯、源码还原到补环境执行,尽量用完整链路的方式讲清楚。
内容更适合有一定 JS 逆向基础、想系统掌握签名定位思路的读者。如果你只是随手想拿现成代码,那这篇不一定适合;如果你想搞明白“为什么是这一步”而不是“背一个结果”,那可以认真看完。
1. 先搞清楚 x-s 在整个请求链路里的角色
1.1 它到底是谁生成、为谁服务的
某红薯网页端的请求流程很典型。你打开任意一个详情页或者搜索接口,打开 DevTools 的 Network 面板,刷新一次就能看到一堆名为 /api/sns/web/v1/... 的请求。随便点开一个请求,在 Request Headers 里能看到 x-s、x-t,有时候还有 x-s-common。
先说结论:这一串 header 是前端 JS 在请求发出之前,用当前请求的 URL、请求体、时间戳等信息动态计算出来的签名。服务端收到请求后会拿同样的参数重新计算一遍,如果跟你提交的值不一致,就直接判定为非法请求。所以它本质上是一个 HMAC 类的签名校验机制,再加了一点“客户端特征”进去,用来做风控辅助判断。
对爬虫开发来说,x-s 是绕不过去的一道关。你不把这块还原清楚,就算把 Cookie 处理得再完美,浏览器能正常访问,你的脚本一跑起来就报错。很多人一上来就搜“x-s 算法是什么”,其实正确思路不是先去问结论,而是先搞清楚它在哪个环节产生的。
1.2 用最笨的办法定位生成位置
定位生成位置,我习惯用 XHR/fetch 断点,而不是直接搜代码。
在某个接口列表页刷新前,切到 DevTools 的 Sources 面板,右侧找到 XHR/fetch breakpoints,点加号输入 api/sns/web 之类的关键字。这样任何发往这个路径的请求都会被断住。重新触发一次搜索,代码就会停在发请求的位置,这时候点击右侧的 Call Stack 往回看调用栈。
需要找的,是那种参数里出现 x-s 赋值的调用帧。正常情况下找两三帧就能看到类似:
javascript复制headers['x-s'] = window.__web_require__('...').default.sign(...)
或者一段自执行函数封装出来的对象方法。到这里就能确定:x-s 不是某个接口单独处理的,而是公共请求库统一注入的。
我见过不少朋友在这个阶段卡住,原因是
