0.11 登录公钥报错、重复认证与设备指纹修复¶
历史记录 / Historical record:本文保留当时的计划、研究或验收证据,不代表 0.11 当前能力全集。现行说明见 文档入口;英文入口见 English overview。
用户反馈 Android 0.11 在反复登录/刷新后出现 Failed to get public key.,信任因子过多时也有同样表现。本轮修复主登录链的可复现缺陷,保留学校实际响应未知这一边界。
已确认的问题¶
currentFingerprint()返回真正用于认证的指纹,persist()却可能保存CampusSession构造器生成的另一个随机指纹。首次登录、仅有指纹但没有 cookie 的快照最容易触发。离线执行实际函数复现了两个值不一致;这会造成设备身份与信任凭据错配。- App 遇到任何登录失败,都会立即用相同凭据完整登录第二次。密码错误、公钥异常和 HTTP 429 都会被重放。20 秒冷却只有内存计时,手动入口没有执行检查,刷新就会清零;库内的自动恢复入口也可绕过它。
- 免密确认返回正常含公钥的登录页时,
passwordlessEntry()丢弃该页面并返回 null。确认请求的网络、HTTP 异常也被吞掉,统一变成公钥失败。 - 登录后漫游也会强制提取公钥,即使收到的是已登录成功页。因此这条错误不能用于判断密码是否已经提交,更不能直接认定设备被封锁。
- 2FA 已失效时静默重建认证链,会在新验证码 hook 建立前丢掉刚输入的验证码。动态口令路径同样有等待时序问题。发码重建失败被吞掉,会误显示已经发送。
修复¶
- 同步 helper、CampusSession 和持久化快照中的设备指纹;无 cookie 的快照也恢复设备身份。
- 取消界面层无条件第二次登录;提交加同步互斥。库内创建新登录链的 admission hook 统一检查并记录 20 秒冷却,再清理认证域 cookie。加入已有链、继续 2FA 不触发清仓或冷却。sessionStorage 保留本 WebView 刷新前的计时,不存账号或凭据。
- 保留免密确认返回的凭据页,最多一次确认 POST 加一次凭据 POST;网络错误和 HTTP 状态原样上传。成功页、2FA 页按对应状态继续。
- 确认表单仅可提交到 HTTPS ID 主机的已知认证端点;公钥文本/input value 兼容并验证曲线点。
- 未知页面、无公钥、信任上限、访问限制、异常表单和确认循环使用稳定错误分类;界面补中英提示。学校明确返回的错误正文保留原文。
- 等待验证码流程就绪才提交代码;死链明确要求重新开始。同方式重发真实调用 SEND_CODE,切换已绑定方式要求重新登录。发送请求失败不再假装成功;提交或发送过程中禁止返回切断当前 UI。后台已经等待的 2FA 按 attemptId 和账号接管,不回放上一轮方法、不覆盖另一账号凭据。
- 信任设备上限继续维持“本次验证可完成,仅不保存新的信任”行为;提示可换行并停留 8 秒,不自动删除旧设备。新签发信任凭据同步到水合缓存,避免恢复旧票。
- 登录与 2FA 错误区提供复制诊断入口;剪贴板不可用时显示可选择复制的文本。
- 登录诊断只记状态、脱敏路径、长度和错误阶段,不记响应 HTML、cookie 值或凭据。
验证与边界¶
node --import tsx tools/login-public-key-test.mjs:28 项行为回归,覆盖正常认证、公钥表单变体、确认回退、HTTP 429、网络异常、成功漫游、2FA、白名单、并发与旧链完成/超时隔离。wrapper 对明确认证错误、403/429 和 AUTH_* 停止自动恢复;普通资源/传输失败仍保留原恢复路径。node tools/login-attempt-state-test.mjs:25 项,执行实际指纹、保存和恢复函数,验证跨刷新冷却、损坏存储和时钟回拨等。node --import ./tools/ts-resolve-register.mjs tools/network-log-privacy-test.mjs:20 项通过。tools/login-recovery-browser-test.mjs在生产预览完成 69 项检查,9 个场景无运行时错误;覆盖手机/桌面公钥异常、429、信任上限、重复提交、刷新冷却、脱敏诊断复制与剪贴板降级、微信/TOTP 验证、发码失败。成功路径确认认证链完成、登录表单卸载并触发进入主界面,信任上限提示完整换行可见。截图与结果位于/Volumes/OneTHUBuild/artifacts/login-recovery/production/。- info-lib build、desktop typecheck 与生产构建通过;
pnpm i18n:handoff已更新翻译目录和批次,pnpm i18n:check为 7493/7493、errors 0。OH 认证/生命周期与清小搭入口回归通过。 - 浏览器验收使用真实 React 页面、模拟原生 IPC 与学校响应,拦截外部网络。夹具未实现首页的全部学校数据接口,后续空响应可触发失登回页;这不证明真实学校会话持续有效,也不代表完整首页端到端、Android 真机或真实账户认证验收。本轮未生成新的安装包。
- 本机不带账号密码请求 WebVPN OAuth 登录入口,最终 ID 页面返回 HTTP 200,17524 字符,公钥为 130 字符,约 76ms。仅证明检查时本机链路正常,不代表受影响用户的网络和当时响应。
- 没有连接 Android 真机,未使用他人账户或主动触发学校限流/设备上限。用户截图实例的唯一根因尚未确定。
回归定位¶
新诊断中 AUTH-FAIL reason=… stage=… 区分页面问题,ILIB status=… final=… chars=… 辅助判断跳转;所有查询票据都剥离。若更新后仍发生,可让用户复制诊断摘要,不需要密码、验证码、cookie 或完整认证网页。