背景
- 早期版本里存在一个
UnlockPage,用于输入“解锁密码/密钥”。 - 后续引入了两套独立概念:
- 应用层 PIN:只保护 UI 进入,需要本地验证,不参与加解密。
- 端到端加密密钥(保险库密码):真正用于派生主密钥,加解密 S3 里的内容。
- 再加上
HomePage内联的解锁 UI,一度出现三个“解锁界面”的影子,极易混淆:- 当时不知道“这里是输入 PIN 还是输入加密密钥”。
- 代码层面也有多处解锁逻辑入口,难以维护。
本次整理的目标是:给 PIN 和加密密钥明确边界,只保留必要的解锁界面。
现状梳理
1. 应用 PIN 解锁流
- 启动时是否需要 PIN,由本地偏好计算:
- 入口:
client/lib/main.dart:12-24 appPinRequired综合了:- 是否设置过 PIN。
- 是否勾选“启动时需要 PIN 解锁”。
- 是否在 24 小时免输入窗口内。
- 入口:
- 真正的 PIN 解锁界面:
- 组件:
AppPinLockPage,client/lib/ui/unlock_page.dart:7-54,56-135 - 特点:
- 只输入数字 PIN,不涉及密码派生。
- 勾选“24 小时内不需要输入 PIN”后,会写入
app_pin_skip_until。 - 验证逻辑调用
AppState.verifyAppPin,client/lib/core/state/app_state.dart:286-289。 - 验证成功后直接导航到
HomePage。
- 组件:
- 这个界面只负责“保护 UI”,不触碰任何加密逻辑。
2. 端到端加密密钥解锁流
- 解锁保险库的核心调用:
AppState.unlock:client/lib/core/state/app_state.dart:393-414- 再经由
ApiClient.unlockVault调用后端/api/v1/auth/unlock:client/lib/core/api/api_client.dart:137-153
- UI 层不再单独弹出“密钥输入页”,而是使用
HomePage的内联解锁区域:- 入口方法:
_handleVaultUnlock,client/lib/ui/home_page.dart:142-164 - 内联解锁组件:
_buildVaultUnlockInline,client/lib/ui/home_page.dart:707-745 - 行为:
- 我在主界面中直接输入“保险库密码”(端到端密钥)。
- 成功后:
- 前端保存密码(如果选择记住)。
- 状态
_vaultStatus变为已解锁,展示文件列表。
- 入口方法:
- 这个流程与应用 PIN 完全解耦,只关心加密和 S3 数据。
3. 已废弃的 UnlockPage 问题
- 旧的
UnlockPage实际上已经不在导航链路里被使用,但代码还留在历史版本里。 - 问题:
- 名称与职责都模糊:“解锁”到底是 PIN 还是加密密钥?
- 很容易和
AppPinLockPage、HomePage内联解锁搞混。 - 对未来阅读者来说,这是一个没有上下文的“幽灵页面”。
决策与调整
决策:只保留两条明确的解锁路径
- 路径 A:应用 PIN
- 配置入口:设置页的“应用 PIN 码”和“启动时需要 PIN 解锁”:
client/lib/ui/settings_page.dart:115-167,445-473
- 解锁界面:
AppPinLockPage。 - 语义:保护 UI,不涉及加密。
- 配置入口:设置页的“应用 PIN 码”和“启动时需要 PIN 解锁”:
- 路径 B:端到端加密密钥(保险库密码)
- 解锁界面:
HomePage内联的_buildVaultUnlockInline。 - 语义:真正控制是否能读写 S3 中的加密内容。
- 解锁界面:
- 任何其他“解锁页面”都视为噪音,不再保留。
实际改动要点
- 保留
AppPinLockPage,确认其仅用于 PIN 流程:- 调用
verifyAppPin,根据结果决定是否进入HomePage。 - 不触碰
unlockVault、不设置 master key。
- 调用
- 删除旧的
UnlockPage实现及其引用:- 移除与端到端密钥相关但已不再使用的 UI 代码。
- 确保路由和设置页中不再出现指向
UnlockPage的导航。
- 确认加密密钥输入只发生在
HomePage:- 内联解锁负责密码输入和错误提示。
- 成功后加载元数据列表。
收获
- 从“有多个解锁页”收敛为:
- PIN 解锁:纯本地 UI 保护。
- 密钥解锁:在 Home 主界面内联完成。
- 对我来说:
- 不再出现“到底应该在这里输入 PIN 还是输入密码”的迷惑对话框。
- 打开应用的第一屏逻辑更清晰:
- 如果开启 PIN 保护:先输入 PIN。
- 进入 Home 后,再根据 S3 状态决定是否需要输入保险库密码。
- 对代码维护来说:
- 只有一个 PIN 页面和一个密钥解锁区域,职责边界清晰。
- 避免未来重构时又误用过时的
UnlockPage。