虎牙登录: 接入hydevice高信任设备指纹与App场景验证支持

- 新增 fingerprint/: node仿真Android WebView运行官方hydevice.js(含WASM加密), 产出与真机同构的高信任sdid
- 新增 device_fingerprint.py: py编排node runner获取sdid, 失败自动降级旧无指纹流程
- login.py: prepare_device优先高信任指纹; 增加App场景常量(appId=5008, appSign=md5(appId+verCode+appKey)[:8], 逆向自APK UdbNetHelper)
- solver: 支持appId/page_url/use_touch_events参数化(App模式); get3使用csid会话id; 识别qr_auth扫码(冷却)与dx_auth短信策略并抛专用异常
This commit is contained in:
yml2213
2026-08-23 17:32:34 +08:00
parent bf2f78aa70
commit 06a0a1e7d3
8 changed files with 438 additions and 16 deletions
+28 -4
View File
@@ -22,6 +22,12 @@ from .cookie_utils import normalize_huya_cookie
APP_ID = "5002"
APP_VERSION = "2.6"
APP_SIGN = "1ce3bf682483d03f146f58232ec10635"
# App 场景(appId=5008): 风控走短信验证(dx_auth)。
# appSign 算法(逆向自 APK com/duowan/kiwi/base/login UdbNetHelper):
# md5(f"{appId}{versionCode}{appKey}")[:8], versionCode=115315(13.4.22),
# appKey 来自 APK 资源 R.string.cgs。
APP_ID_MOBILE = "5008"
APP_SIGN_MOBILE = "60576904"
LCID = "2052"
PASSWORD_LOGIN_URI = "30001"
DF_TOKEN_URL = "https://df.huya.com/web/df/token"
@@ -141,6 +147,7 @@ class HuyaPasswordLogin:
self.context = generate_context(self.device_id, self.mid)
self.middle_url = f"https://udblgn.huya.com/web/middle/{APP_VERSION}/{self.exchange}/https/{self.device_id}"
self.sdid = ""
self.sdid_source = ""
self.session = session or requests.Session()
self.session.trust_env = False
@@ -199,7 +206,20 @@ class HuyaPasswordLogin:
})
def prepare_device(self) -> str:
"""获取虎牙风控 sdid。"""
"""获取虎牙风控 sdid(优先 hydevice 高信任指纹,失败降级旧版)"""
from .device_fingerprint import get_huya_sdid
try:
result = get_huya_sdid(app_id="5008", timeout=self.timeout)
if result.sdid:
self.sdid = result.sdid
self.sdid_source = result.source
logger.debug("虎牙 sdid 来源: {}", result.source)
return self.sdid
logger.warning("虎牙高信任指纹未返回 sdid: {},降级旧流程", result.message)
except Exception as exc: # noqa: BLE001
logger.warning("虎牙高信任指纹异常: {},降级旧流程", exc)
token_payload = {"encryptVersion": "1.0.1", "fingerprintVersion": "1.2.41"}
token_res = self._request_json("post", DF_TOKEN_URL, "获取虎牙 df token", json=token_payload)
token = token_res.get("data", {}).get("token")
@@ -258,8 +278,8 @@ class HuyaPasswordLogin:
)
def _solve_verification(self, payload: dict) -> str:
"""处理 10030/10039 风控并返回 authId。"""
from .verification import HuyaVerificationSolver
"""处理 10030/10039 风控并返回 authId;未下发图形验证时返回空串"""
from .verification import HuyaNoSessionError, HuyaVerificationSolver
solver = HuyaVerificationSolver(
cookie=self.session.cookies.get_dict(),
@@ -269,7 +289,11 @@ class HuyaPasswordLogin:
proxies=self.session.proxies,
timeout=self.timeout,
)
verify_data = solver.solve(payload)
try:
verify_data = solver.solve(payload)
except HuyaNoSessionError as exc:
logger.warning("虎牙未下发图形验证({}),将直接重试登录", exc)
return ""
auth_id = verify_data.get("authId") if isinstance(verify_data, dict) else ""
if not auth_id:
raise HuyaLoginError(f"虎牙风控验证未返回 authId: {verify_data}")