场景
我在给一个单人内部使用的 PRD 填表工具加云端草稿箱功能。产品诉求很朴素:能换设备接着填。
工具本身部署在 xxx.pages.dev/some-tool 这样的 Cloudflare Pages 上,配了 noindex 挡搜索引擎,没做任何登录 / 授权。
产品负责人的原话:
「需要增加一个线上的草稿箱,身份验证的问题需要考虑吗?没拿到链接谁也进不去。」
听起来天经地义。但这句话是个幻觉,而且是很多人做小工具时都会踩的幻觉。
为什么「没拿到链接谁也进不去」不成立
拆开 4 层:
1. noindex 只挡搜索引擎,不挡任何有链接的人
CF Pages / Vercel / Netlify 这类静态托管,默认对任何发起 HTTP 请求的人都返回内容。<meta name="robots" content="noindex"> 只让 Google / Bing 不索引,但任何拿到 URL 的人都能直接访问。
2. URL 泄漏路径远多于想象
盘一下真实世界里 URL 会「意外」跑到哪:
- 发到 Telegram / 微信 / Slack:服务端明文存
- 手机截图里带着地址栏:iCloud / Google Photo 自动同步
- 浏览器书签同步:多设备协同 = 多设备风险面
- 未来任何一次协作时贴给别人:@某人时就漏了
- CF Pages access log:CF 内部员工理论上可见
- 复制粘贴时误发:发错群
这些路径不需要你「故意」,你只要用这个工具,泄漏概率就是不为零的。
3. URL 本身可以猜
- 域名
xxx.pages.dev是公开可查的 CF 子域 - 路径
/some-tool是自然英文,不是随机哈希
即便概率很低,「不可能」和「概率低」是两个概念。攻击者只要能自动化扫,时间就是成本。
4. 一旦加了云端存储,风险等级质变
这是最关键的一层:
- 只有本地存储(localStorage)时:URL 泄漏 → 别人只看到工具本身,你的数据在你自己浏览器里
- 加了云端存储、没身份验证时:URL 泄漏 → 别人能看你的实际内容,能覆盖你的实际内容
这是两个数量级的安全等级差。
「概率低」能推出什么
P(泄漏) 极小 只能推出:
- ✅ 不用上企业级零信任
- ✅ 不用请安全审计
- ✅ 防护方案可以低成本
不能推出:
- ❌ 不用做访问控制
- ❌ 不做加密
这是我今天想沉淀的一条原则:
「概率低」是「防护成本可以低一档」的理由,不是「不做防护」的理由。
反过来想更清楚:如果「概率低」可以推出「不做」,那我们所有的备份、异地容灾、断路器都可以撤了 —— 因为「机器不会那么容易挂」也是一个「概率低」的判断。
工程决策不看单次概率,看「失败时的代价 × 单位时间累积概率」,后者才是决定要不要做防护的东西。
我给出的落地方案(自留)
回到那个 PRD 填表工具,给的方案是密码 + Cloudflare KV + 前端 AES-GCM 加密的零知识(zero-knowledge)架构:
┌─────────────────────────────────┐
│ Tool (浏览器) │
│ 用户输密码 → 前端 AES 加密 │
│ (密码永不发到服务器) │
└──────────────┬──────────────────┘
│ HTTPS
▼ 加密后的 blob
┌─────────────────────────────────┐
│ Cloudflare Worker │
│ 只转发,不解密 │
└──────────────┬──────────────────┘
│
▼
┌─────────────────────────────────┐
│ Cloudflare KV │
│ 存的就是密文 base64 │
└─────────────────────────────────┘
核心原则:
- 密码只在浏览器里,派生成 AES key(PBKDF2-SHA256 210k iterations),从不发到服务器
- 服务端全程只看到加密后的乱码,KV 里存的都是密文
- owner ID 用 HMAC-SHA256 派生,服务端看到的是 16 位 hex 索引,不知道对应的是谁
- Worker 加 rate limit 挡暴力猜密码(每 IP 每分钟 60 次)
- body size guard(比如 100KB)防打爆 KV
攻击面诚实告知:
- 攻击者拿到 URL → 能看工具、能拉密文 → 猜密码,PBKDF2 210k 让暴力破解慢到不现实
- 攻击者拿到 URL + 密码 → 能全读全改(这就是密码泄漏的后果,符合预期)
- 密码忘了 → 草稿彻底丢(零知识的代价,不可逆)
成本对比:
| 方案 | 工程量 | 别人拿到 URL 后果 |
|---|---|---|
| A · 裸奔(不做) | 30 分钟 | 能读能改所有草稿 |
| B · 密码 + KV + 加密 | 1.5 小时 | 密码错就 403,读改都不行 |
| C · GitHub OAuth 登录 | 3-4 小时 | 只有指定账号能进 |
单人自用场景选 B,不选 C —— C 是过度设计,给一个人做多用户身份系统是浪费。未来真要多人协作,B 再升 C 也不贵。
归纳
小工具不做安全,通常不是想不到,而是脑子里出现了「反正没人会盯上我这么小的东西」的幻觉。把这个幻觉拆掉,决策路径就清楚了:
- 只要功能会存用户实际数据 → 访问控制是硬需求,不管使用规模多小
- 「概率低」不能作为「不做」的理由,只能作为「防护成本可以低一档」的理由
- 零知识架构在「服务端也不信」的场景里特别值 —— 前端加密的一点点工作量,换来服务端 zero-liability,长期收益远超短期投入
留一句给未来的自己:
每次想说「反正 xxx 概率很低」的时候,把这句话补完:「所以我把防护成本降到 xxx」,而不是「所以我不做」。
马启航Marvis