新版(v0.2)把概念缩减到 两个:Sync Secret 和 Admin Key。本文解释它们的区别、组合行为、以及典型使用场景。
作用:身份证明。承担三件事:
- 同步写入鉴权(PUT /api/sync)
- 云端浏览鉴权(POST /api/admin/list-all)
- 分享写入鉴权(PUT /api/share,PUT /api/sharekey)
特性:
- 由你(管理员)部署时设置;客户端登录时输入
- 客户端仅保存在当前标签页会话的 sessionStorage;关闭浏览器会话后需要重新输入
- 解锁后整个会话内有效(管理员模式 sessionStorage 标志)
- 忘记可以改服务端环境变量重新设置
分享链接恢复材料默认不保存。生成分享时可显式选择保存到
/api/sharekey,供其他管理员设备重新复制链接;无口令分享开启该选项后,服务端管理员也具备解密能力。口令保护的分享只保存被口令包裹后的恢复材料。
兼容字段:旧版
SYNC_TOKEN和KV_ADMIN_KEY仍然有效,与ADMIN_KEY等价。所有 endpoint 的鉴权统一在functions/_lib/auth.js处理,使用恒时比较以降低时序攻击面。
作用:端到端加密密钥。客户端用 PBKDF2(secret, "sync:" + syncId) 派生 AES-GCM 256 位密钥,加密整个 items 列表后才上传到云端。
特性:
- 由你为每个项目独立设置
- 跨设备必须一致(否则解不开同一份云端密文)
- 服务端永远看不到,也无法重置
- 忘记后云端数据无法恢复(除非启用了 RSA 密钥托管)
| 模式 | GET /api/sync | PUT /api/sync | 适用场景 |
|---|---|---|---|
strict(默认) |
需要 Admin Key | 需要 Admin Key | 个人 / 小团队私用,最大隐私 |
open |
公开(任何人可下载密文) | 需要 Admin Key | 公开实例,密文靠 Sync Secret 保护即可 |
若服务端没有配置任何密钥(既没 ADMIN_KEY 也没 SYNC_TOKEN),则等价于
open模式且写入也不鉴权——仅适合内网或测试。
不配置任何环境变量也可以。访客:
- 打开页面 → 加 2FA → 看验证码 → 关闭浏览器后数据仍在
- 数据只在浏览器 localStorage,不会上传任何服务端
- 完全离线可用,PWA 装到主屏
注:如果服务端配置了
ACCESS_GATE,访客需要先通过站点访问口令才能进入页面,但数据本身仍只在本地。
- 部署时配
ADMIN_KEY = "强随机字符串-自己记住" SYNC_MODE不设 → 默认 strict(最严)- 设备 A:
- 关于 → 输入 Admin Key 登录
- 项目 → 新建项目(项目名 / Sync ID / Sync Secret)
- 自动推送,或手动点"⬆ 推送"
- 设备 B:
- 同样登录 Admin Key
- 新建项目,填完全相同的 Sync ID + Secret(项目名可不同)
- 点"⬇ 拉取"
期间任何普通访客的 GET 请求都返回 401,看不到任何云端数据。
- 配置
ADMIN_KEY但SYNC_MODE = "open" - 任何人可以下载密文,但没 Sync Secret 解不开
- 只有你能写入
担心忘记 Sync Secret 后数据无法恢复?启用密钥托管:
- 生成一对 RSA 密钥(推荐 4096 位)
- 在客户端"管理员 → 密钥托管"启用,填公钥
- 选中云端项目 → 点"托管选中项目密钥"
- 后端
vault:<syncId>存储用 RSA-OAEP+AES-GCM 加密的 Sync Secret - 私钥离线保存(U 盘 / 密码管理器)
- 任何时候,用私钥从"找回选中项目密钥"取回 Secret
无论是否同步,本地数据可选用主密码加密:
- 设置后:localStorage 中是
{v:2, iv, ct}格式的 AES-GCM 密文 - 重启浏览器需要先输入主密码才能解锁
- 与 Sync Secret 完全独立(一个保护本地,一个保护云端)
| 操作 | 无项目 | 有项目(无 Admin Key) | 有项目(有 Admin Key) |
|---|---|---|---|
| 添加 / 复制 / 删除(本地) | ✅ | ✅ | ✅ |
| 推送到云端 | ❌ | ❌ (401) | ✅ |
| 从云端拉取(strict) | ❌ | ❌ (401) | ✅ |
| 从云端拉取(open) | ❌ | ✅ 但密文 | ✅ |
| 分享验证码 | ✅ | ❌ (写入需要 Admin Key) | ✅ |
| 撤销分享 | ✅ | ❌ | ✅ |
| 云端浏览 / Vault / 迁移 | ❌ | ❌ | ✅ |
| 现象 | 检查 |
|---|---|
| 401 推送失败 | 抽屉「关于」是否登录 Admin Key?key 是否与服务端 ADMIN_KEY 一致? |
| 拉取后数据空 | Sync ID 是否与对端一致? |
| 拉取后解密失败 | Sync Secret 是否与对端一致? |
| 摄像头扫描不工作 | 必须 HTTPS(npm run dev:https);不支持的浏览器请用图片识别或链接粘贴 |
| 改了代码刷新没生效 | Service Worker 缓存。Application → Service Workers → Unregister 后刷新 |
| 升级后看到空白 | 主密码加密的数据需要先在抽屉"数据"里解锁 |
抽屉「项目」里有「📊 全部项目(汇总视图)」入口。它是纯本地的虚拟视图:
- ✅ 显示你已创建的所有项目的验证码合并结果
- ❌ 不会主动拉取你不知道的云端项目
- ❌ 不会显示其他用户的数据
- 工作原理:遍历
state.syncProjects数组,把每个项目的itemsData合并
要看到一个云端项目,必须主动在「项目 → 新建」中填它的 Sync ID + Secret。