feat(huya): 零设备 dfpReport 注册链迁入 core/huya 并接入生产登录

- 新增 core/huya/dfp_register: 随机 4146B cw 生成 + 注册响应解析 (t1/t2/t5),
  修复 JSON 模板 %s 数不匹配的 TypeError bug
- app_login 每次 WUP 登录前执行注册链取新 safedeviceid/device_id,
  不再读取画像旧固定值; 注册失败抛 HuyaAppLoginError 终止, 不静默回退旧链
- device_profile 移除固定 SAFEDEVICEID_DEFAULT, 画像只承载 soft 字段
- tools/huya_device_register 同步零设备生成链路 (--gen/--gen-login)
- 新增 tests/test_huya_dfp_register (9 项), 扩展 test_huya_app_login 注册接线 (4 项)
This commit is contained in:
yml2213
2026-08-27 17:47:53 +08:00
parent 36325cf639
commit 0c86e182b0
6 changed files with 520 additions and 37 deletions
+65 -1
View File
@@ -19,8 +19,14 @@ from core.huya import (
login_huya_app_password,
login_huya_password,
)
from core.huya.app_login import (
DEFAULT_GOLDEN_DEV,
login_cred_with_flow,
wup_password_login_raw,
)
from core.huya.cert_forge import build_p1, decrypt_cert, forge_cert, parse_p1
from core.huya.device_profile import generate_profile, get_profile
from core.huya.dfp_register import DfpRegistrationError
from core.huya.envelope_forge import Envelope
from core.huya.login import HuyaLoginResult
from core.huya.nonce_forge import K1_DEFAULT, gen_nonce
@@ -97,6 +103,9 @@ class TestHuyaAppLogin(unittest.TestCase):
self.assertEqual(len(p1["fingerprint"]), 40)
self.assertEqual(len(p1["device_id"]), 40)
self.assertEqual(p1["hdid"], "ed0db8334cadd236c00cadf7e11ab5a5")
# 画像不再承载 safedeviceid:该令牌由 dfp_register 注册链每次登录前签发
self.assertNotIn("safedeviceid", p1)
self.assertNotIn("safedeviceid", DEFAULT_GOLDEN_DEV)
p2 = get_profile("test_user_account_123")
p3 = get_profile("test_user_account_123")
@@ -107,7 +116,8 @@ class TestHuyaAppLogin(unittest.TestCase):
pkt = build_password_login_wup(
uid_str="300023887",
sha1_password="772ed992b0e161276f44ec63671e60155c506294",
safedeviceid=dev["safedeviceid"],
# 注册链签发格式: 180B base64 action 令牌
safedeviceid="A" * 180,
hdid=dev["hdid"],
session=3251699,
trace_id="test-trace-id",
@@ -118,6 +128,60 @@ class TestHuyaAppLogin(unittest.TestCase):
total_len = struct.unpack(">I", pkt[:4])[0]
self.assertEqual(total_len, len(pkt))
# ---- 新设备注册链 (core/huya/dfp_register) 生产接入测试 ----
def test_wup_login_skips_registration_when_safedeviceid_given(self):
"""显式传入 safedeviceid 时不再触发注册链(风控重试复用同一注册结果)。"""
with patch("core.huya.app_login.register_device") as m_reg, \
patch("core.huya.app_login.build_password_login_wup", return_value=b"pkt"), \
patch("core.huya.app_login.requests.post",
return_value=MagicMock(status_code=200, content=b"")):
wup_password_login_raw("300023887", "pw", safedeviceid="A" * 180)
m_reg.assert_not_called()
def test_wup_login_registers_fresh_device_when_safedeviceid_missing(self):
"""未传 safedeviceid 时先注册,注册签发的 action/device_id 进 WUP 帧。"""
new_action = "B" * 180
new_device_id = "c" * 40
captured = {}
def fake_build(*args, **kwargs):
captured["args"] = args
return b"pkt"
with patch("core.huya.app_login.register_device",
return_value=("a" * 32, new_action, new_device_id)) as m_reg, \
patch("core.huya.app_login.build_password_login_wup", side_effect=fake_build), \
patch("core.huya.app_login.requests.post",
return_value=MagicMock(status_code=200, content=b"")):
wup_password_login_raw("300023887", "pw")
m_reg.assert_called_once()
# args: uid_str, sha1, safedeviceid, hdid, session, traceId, ua, dev
self.assertEqual(captured["args"][2], new_action)
self.assertEqual(captured["args"][7]["device_id"], new_device_id)
# 画像默认值里的旧 device_id 被注册结果覆盖,而非沿用
self.assertNotEqual(
captured["args"][7]["device_id"],
DEFAULT_GOLDEN_DEV["device_id"],
)
def test_wup_login_registration_failure_is_explicit(self):
"""注册失败必须抛错终止,禁止静默回退旧链(不发任何登录请求)。"""
with patch("core.huya.app_login.register_device",
side_effect=DfpRegistrationError("注册链超时")) as m_reg, \
patch("core.huya.app_login.requests.post") as m_post:
with self.assertRaises(HuyaAppLoginError):
wup_password_login_raw("300023887", "pw")
m_reg.assert_called_once()
m_post.assert_not_called()
def test_login_cred_flow_registration_failure_is_explicit(self):
"""login_cred_with_flow 注册失败同样包装为 HuyaAppLoginError 显式失败。"""
with patch("core.huya.app_login.register_device",
side_effect=DfpRegistrationError("注册链 HTTP 500")):
with self.assertRaisesRegex(HuyaAppLoginError, "注册失败"):
login_cred_with_flow("300023887", "pw")
def test_router_functions(self):
mock_res = HuyaLoginResult(
success=True,