feat(qs): 接入官方签名模块、修复扫码登录链路、新增本机登录脚本

- passport:响应自带的 qrcode 图指向已 404 的旧扫码页
  (ucenter_web/app/sdk-next),抖音扫码会提示「无法访问页面」;改为用
  qrcode_index_url 的 token 重建官方 bff-pc.qishui.com/light/invoke/scan_login
  地址,与客户端 renderer 的 getHandleScanCodeH5Img 算法一致。同时状态
  映射按官方 renderer 语义对齐(1/new 待扫码、2/scanned 已扫码待确认、
  3/confirmed 已确认),并采集轮询下发的 Set-Cookie、响应带 redirect_url
  时补跳一次,否则拿不到 sessionid
- qs/mssdk:进程内加载官方 bdms.node 生成 X-Helios / X-Medusa 签名,
  不另起 HTTP 签名服务;缺原生模块时整体降级,不影响匿名可用
- scripts/qs-local-login.mjs:直接读本机官方客户端的 Cookies 与 DeviceV1
  写入 data/auth.json,免扫码(独立脚本,不参与服务运行)

为什么需要 mssdk 签名:汽水对未签名请求回 HTTP 200 + 0 字节,把失败伪装
成空成功,没有签名就分不清「接口异常」与「风控拦截」。
This commit is contained in:
snowy-yang committed 2026-10-03 00:27:19 +08:00
1 parent 68e071b166
commit de2dd311ee
6 files changed
+574 -92

No files matched your search

+18 -1
View File
@@ -151,4 +151,21 @@ export const getDevice = async (): Promise<QsDevice> => {
export const hasDevice = (): boolean =>
Boolean(cachedDevice || (getCredentials('_qs_device') as QsDevice | null)?.device_id)
export default { registerDevice, getDevice, hasDevice }
/**
* 设备身份(同步读,不触发注册):已注册设备优先;尚未注册时用独立生成的
* `_qs_passport_device`,避免覆盖注册记录。护照/签名模块共用,保证「同一设备」。
*/
export const getDeviceIds = (): { deviceId: string; installId: string } => {
const registered = getCredentials('_qs_device') as QsDevice | null
if (registered?.device_id && registered?.install_id) {
return { deviceId: String(registered.device_id), installId: String(registered.install_id) }
}
const existing = getCredentials('_qs_passport_device') as { deviceId?: string; installId?: string } | null
if (existing?.deviceId && existing.installId) return { deviceId: String(existing.deviceId), installId: String(existing.installId) }
const now = Date.now()
const ids = { deviceId: String(now), installId: String(now + 1) }
setCredentials('_qs_passport_device', ids)
return ids
}
export default { registerDevice, getDevice, hasDevice, getDeviceIds }