Files
live-hub-py/docs/HUYA_CHAT_缺失字段补齐方案.md
T

191 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 虎牙网页 Cookie 缺失字段补齐方案(2026-09-01 晚)
> 目标:账号 19507362959DB id=58yyuid=1199664135026)跑通精英宝典 WSS
> query_game_namecheckUserBindGameAccount/ query_pointsgetUserScore)。
> 当前账号 cookie 仅 16 字段(登录凭据),对比 9.1 抓包 42 字段缺 26 个。
> 本文档按"浏览器实测来源 → 生成方案"逐字段确定,重点分析 4 个核心设备字段。
## 一、背景结论(已有证据)
- 9.1 抓包(2026-09-01 09:3642 字段 cookie`guid/game_did/_qimei_uuid42/udb_*` 等全部齐全,
上午所有业务接口成功;当天 21:40 用同一 cookie 逐字节重放,**带 cookie 的业务接口全部返回
905/259**,不带 cookie 的 getActInfo/getActTaskDetail 仍成功 → 905 是 **udb 登录态过期**
不是请求帧格式问题(重放原字节即可复现)。
- 浏览器实测(真实 Chrome CDP,`evidence/browser_cookie_harvest/report.md`):
7 个必填网页设备字段全部由**页面脚本写 document.cookie** 或**服务端匿名接口下发**产生:
| 字段 | 产生机制 | 协议可否复刻 |
| --- | --- | --- |
| `udb_deviceid` | middle/anonymousLogin Set-Cookie10 年) | ✅ 已接入 anon_device |
| `udb_anobiztoken` | anonymousLogin 响应 biztoken | ✅ 已接入 anon_device |
| `udb_anouid` | anonymousLogin 响应 uid | ✅ 已接入 anon_device |
| `udb_guiddata` | middle URL 第三段 hex32(客户端自选) | ✅ 已接入 anon_device |
| `guid` | `HyUDBWebSDK-Exchange-2.4.js` 写 document.cookie | ❓ 脚本语义待复刻 |
| `_qimei_uuid42` | QIMEI SDK 脚本写 document.cookie | ❓ 脚本语义待复刻 |
| `__yamid_new` | 门户业务脚本写 document.cookie | ❓ 脚本语义待复刻 |
| `game_did` | 门户业务脚本写 document.cookie | ❓ 脚本语义待复刻 |
## 二、账号 58 现状(16 字段)
`udb_passport, username, udb_cred, udb_uid, yyuid, udb_biztoken, udb_version,
udb_origin, udb_status, sdid, hdid, udb_anouid, udb_anobiztoken, udb_deviceid,
udb_appid, udb_guiddata` —— 4 个匿名设备字段已有(anon_device 协议),
**缺 `guid/game_did/_qimei_uuid42/__yamid_new` 4 个核心 + 22 个统计字段**
## 三、缺失字段补齐方案(逐字段)
### 3.1 四个核心设备字段(本轮重点分析)
| 字段 | 9.1 值形态 | 浏览器首次出现 | 补齐方案 |
| --- | --- | --- | --- |
| `guid` | 32 hex`0a7d…` 前缀 | udbres.huya.com SDK 脚本 | 待 SDK 逆向;**格式** 32hex |
| `game_did` | 35 位字母数字 | liveapi.ip/getIpLocation 后门户脚本 | 待门户脚本逆向;格式 alnum |
| `_qimei_uuid42` | 42 hex`1a901…` 前缀 | QIMEI SDK 脚本 | 待 SDK 逆向;格式 42hex |
| `__yamid_new` | 32 hex 大写 | 门户脚本 | 待门户脚本逆向;格式 32hex 大写 |
浏览器 round1 同一字段多次出现均**值稳定**(跨 profile 稳定):`_qimei_fingerprint`
恒为 `2822a43b5a3bd016fc844218c35c8a74``_qimei_uuid42` 前缀恒为 `1a901…`
`guid` 前缀恒为 `0a7dfaa2…` → 存在固定前缀/哈希结构,**随机值可能被风控识别**,
需还原生成算法。
### 3.2 统计/会话字段(随机即可,服务端仅记录)
| 字段 | 生成规则 | 9.1 样例 |
| --- | --- | --- |
| `SoundValue` | 固定 `0.50` | `0.50` |
| `alphaValue` | 固定 `0.80` | `0.80` |
| `isInLiveRoom` | 固定 `true` | `true` |
| `__yasmid` / `__yamid_tt1` | 17 位随机小数,两者同值 | `0.24859634691671784` |
| `udb_passdata` | 固定 `3` | `3` |
| `_rep_cnt` / `rep_cnt` | 随机 0-9 | `5` / `7` |
| `udb_accdata` | 固定 `undefined` | `undefined` |
| `h_unt` | 当前时间戳(秒) | `1788226396` |
| `__yaoldyyuid` | = yyuid | `1199666914671` |
| `_yasids` | `__rootsid%3D`+32hex 大写 | `__rootsid%3DCBCC34C4…` |
| `Hm_lvt_5170…` | 当前时间戳 | `1788226384` |
| `Hm_lpvt_5170…` | 当前时间戳 | `1788226571` |
| `HMACCOUNT` | 16 hex 随机(百度统计下发) | `1B08C0532E777923` |
| `huya_flash_rep_cnt` | 随机整数 | `136` |
| `huyasp_rep_cnt` | 随机整数 | `9` |
| `huya_hd_rep_cnt` | 随机整数 | `22` |
| `huya_web_rep_cnt` | 随机整数 | `507` |
### 3.3 已有字段(保持真实值)
`udb_cred/biztoken/uid/yyuid/passport/version/origin/status/appid/username`(登录凭据)、
`sdid/hdid`(设备指纹)、`udb_deviceid/udb_guiddata/udb_anobiztoken/udb_anouid`anon_device)、
`huya_ua`normalize 注入)。
## 五、实现与端到端验证(2026-09-01 晚)
实现(commit `5dc7365`):
- 新增 `core/huya/web_cookie_fields.py``fill_web_cookie_fields(cookie, guid, uid)`
补齐 4 核心(guid 用 wsLaunch 会话值,`_qimei_uuid42`/`__yamid_new`/`game_did`
随机对齐格式)+ qimei 皮肤 + 22 个统计/会话字段;`missing_web_cookie_fields` 返回缺失集合。
- `core/huya/elite_session.py`:活动通道初始化时若缺网页字段,先 wsLaunch 预取
服务端认可的会话 guid → 补齐 cookie → 重建会话;业务 RPC 统一走补齐后的
cookie`_resolve_cookie`)。
端到端结果(账号 id=58yyyyuid=1199664135026,原始 16 字段登录态):
| 任务 | 结果 |
| --- | --- |
| `query_game_name`b_act_id=9271 | **success**,角色=收麦季(手Q/苹果iOS),game_name=和平精英,已绑定(QQ 昵称"羊"),change_bind_day=7 |
| `query_points`sid=2203 | **success**msg=请求成功,gainScore=4880 / usedScore=4880 / available=0 |
修复前同类任务全部报"接口无响应"getConfig 超时);修复后 Web API
`POST /api/huya/tasks/batch`,账号 58)两条任务均 success 落库。
复现命令:
```bash
cd /Users/yml/codes/live-hub-py
.venv/bin/python /tmp/huya_test_session.py # 原始 DB cookie → 自动补齐 → 查角色/积分
./dev.sh # 界面 http://localhost:5174 → 精英宝典
```
## 六、风险与验证要求
## 七、各通道 Cookie 依赖矩阵(2026-09-01 晚实测)
不同通道对网页设备态字段的依赖不同,补齐策略按通道区别:
| 通道 | 代表接口 | Cookie 使用方式 | 原始 16 字段能否工作 |
| --- | --- | --- | --- |
| 活动 WSS`mobileui`/`webActUI` | getConfig / getUserScore / checkUserBindGameAccount / scoreExchangePrize | AUTH 帧 + 业务 tReq 均带完整 cookiewsLaunch 会话 guid 需回写 | ❌ 缺 4 核心字段时 getConfig 超时;**需补齐**(已接入 elite_session |
| 商城 WSS`shopMiddleUI`m-shop.yaoguo.com | getGoodsInfoV5 / createOrderV5 / payOrderSubmit | 业务 tReq `UserId.sCookie` 带完整 cookie`sGuid` 置空(HAR 实证) | ✅ 实测原始 cookie 正常响应(403 只是业务参数校验) |
| HTTP RPCcdnws.api.huya.com POST | query_user_score / get_act_prize_list / build_bind_urls / get_livelink_mini_qrcode | baseinfo + 业务 tReq 带完整 cookie`_resolve_cookie_guid` 自动用 guid→udb_guiddata→sha256 派生 | ✅ 实测原始 cookie 直接返回 status=200(积分 4880 |
要点:
1. **活动 WSS 是唯一强校验网页设备态的通道**AUTH/getConfig 前置就失败(无响应),
补齐字段后成功(commit `5dc7365`)。
2. **商城 WSS 不校验**`UserId.sGuid=""` 且 cookie 原样发送,服务端接受原始登录态
(实测 getGoodsInfoV5 返回业务 403 而非连接/解析错误)。
3. **HTTP RPC 自带 guid 派生**:缺 `guid` 时依次用 `udb_guiddata[:32]`、`yyuid|udb_uid|
udb_passport|username|udb_biztoken` 的 sha256 派生,业务请求体可带原始 cookie
直接成功 —— 这是「活动接口当前主要依赖核心认证字段」的佐证(与
`HUYA_COOKIE合并审计与来源矩阵.md` 结论一致)。
4. 因此**没有其他必须补齐的 cookie 字段**:活动 WSS 之外,商城 WSS 与 HTTP RPC 用
原始登录态即可跑通。剩余未实测的链路(商城下单/支付等)依赖的仍是同一份
原始 cookie + `udb_cred/biztoken` 登录态,不涉及网页设备字段的新增要求。
## 八、商品/兑换全链路验证(2026-09-01 晚,活动 WSS
补齐会话后逐接口实测(账号 58,sid=2203):
| 接口 | 请求参数 | 响应 |
| --- | --- | --- |
| `getActPrizeList` | sid=2203 | status=20029 个商品 / 2 分类(限量返场/精英专享),如 pid=13161 破片手榴弹 3600 分 |
| `getActPrizeDetail` | sid=2203, pid=13161 | status=200,详情正常(score=3600、频次 600/3、时段 00:00-23:59:59、可兑) |
| `getUserPrizeRecords` | sid=2203 | status=200,历史 2 条(赤蝎幽灵 3600 / 萌神柯基 1280,已发放) |
| `scoreExchangePrize` | sid=2203, pid=13161 | status=604"兑换货币不足" —— **协议往返成功**,业务侧拒绝(账号可用积分 0) |
结论:商品刷新/选择/兑换接口与 9.1 抓包字节逐一对齐(sid/pid/ip/clientEnv/source/
isRole),RPC 往返全部正常;604 是账号真实积分状态(历史兑换已用 4880/4880),
非协议问题。兑换成功路径需账号有可用积分后复测;发起兑换前 `query_user_score`
的 `available_score` 先行校验可避免 604。
1. `guid/_qimei_uuid42/__yamid_new/game_did` 的**真实性/关联性**服务端是否校验未知;
必须用生成值跑通线上活动 WSS 全链路才能定论,不能只过长度测试。
2. 统计字段随机值不影响接口语义,但**顺序**建议与 9.1 cookie 保持一致以便对照。
3. 补齐后仍需**新鲜的 udb 登录态**(905 = 过期),登录链路见 `app_login.py`。
## 九、浏览器注入 ck 未登录的根因(2026-09-01 晚实测确认)
现象:把 App 扫码登录产出的 41 字段网页 ck 注入浏览器,打开 www.huya.com 顶部仍显示
"登录"按钮(未登录)。
排查过程(CDP 有头 Chrome 实测):
1. ck 本身有效:curl 带该 ck 请求
`l.huya.com/udb_web/udbport2.php?m=HuyaLogin&do=checkLogin` 返回
`{"isLogined":true,"userName":"hy_300539756","uid":"1199667330433",...}`
8.31 真实扫码登录抓包的 checkLogin 成功值与 verify data:null 均一致。
注意:`user.huya.com/liveHttpUI/checkUserTimeIsLogin` 的 `iIsLogin:0` 不判定
登录态 —— 真实网页 ck 抓包同样为 0,可排除。
2. `web/cookie/verify` 的 `data:null` 也是正常成功形态,非未登录信号。
3. document.cookie 检查发现:注入后页面里只有设备字段(guid 等)、没有
udb_uid/udb_cred/udb_biztoken/yyuid —— 登录凭据没有被 www.huya.com 子域携带。
**根因:Network.setCookie 的 domain 参数不能写 `huya.com`,必须写 `.huya.com`
(带前导点)。**
- `domain="huya.com"`(无前导点)→ Chrome 存为 **host-only cookie**,只有精确访问
`huya.com` 时才发送;`www.huya.com` / `l.huya.com` / `udblgn.huya.com` /
`user.huya.com` 等**所有子域都不会携带** → 页面意义上的登录判定失败。
- `domain=".huya.com"`(带前导点)→ 存为 **domain cookie**huya.com 及其全部子域
都携带。实测注入后 `document.cookie` 含全部字段,顶部导航"登录"按钮消失、
出现登录用户专属项(如"关注")。
正确注入姿势(CDP):
```json
{"method":"Network.setCookie","params":{
"name":"udb_uid","value":"1199667330433","domain":".huya.com",
"path":"/","secure":false,"httpOnly":false}}
```
手工用浏览器插件/DevTools 注入时同样注意:Domain 填 `.huya.com`(用户输入时 Chrome
会规范化为前导点形式;若插件按 host-only 保存则无效)。HttpOnly 无需设置 ——
uzb_* 登录凭据在真实网页中可由脚本读取,非 HttpOnly。