无账户身份识别
设计意图
早期不做传统用户系统(邮箱注册 / 账号密码那一套),每个访问者通过浏览器获得身份令牌即可开写。目标是零上手成本——打开就能用。
后来为解决「换设备 / 清 Cookie 认不出人」,在仍是访客模型的前提下,增加了可选的登录密码;恢复码则是更早的自助找回手段,现已边缘化。详见 恢复码与身份找回。
身份模型
访客注册(输入昵称,可选设密码)
│
├─ 服务器生成 UUID(visitor_id)
├─ 生成高熵令牌(visitor_token,32 字节随机数 → base64url)
├─ 服务器只存储 SHA-256(令牌)(以及可选的密码哈希)
└─ 通过 HttpOnly Cookie 将原始令牌下发给浏览器
后续请求
└─ 浏览器自动携带 Cookie
└─ 服务器从 Cookie 读取令牌,验证 SHA-256 匹配 → 识别访客
前端不存储任何认证令牌,日常鉴权凭据由 HttpOnly Cookie 管理,XSS 无法直接读到令牌。
Cookie 有效期
身份 Cookie 默认有效期为 10 年,实践中等同于「长期保持登录」。只要不主动清除浏览器站点数据,同一浏览器上会一直认得你。
💡 即使服务端重启或重新部署,已有 Cookie 在未过期前依然有效。
为什么这样做
- 低门槛:不必先走邮箱验证;起个昵称就能写
- 令牌不落前端脚本可读存储:日常身份靠 HttpOnly Cookie
- 跨端续身份(后来补上):设密码后可用「用户名 + 密码」在其他设备登录;未设密码则基本绑在当前浏览器
跨设备 / Cookie 丢失时
推荐顺序:
- 用户名 + 密码登录(设置页可管理登录密码)
- 恢复码(早期方案,登录弹窗次要入口;见 恢复码)
- 管理员 访客迁移(运维兜底)
访客迁移(管理员)
若用户既无密码又无可用恢复码,部署方可在服务器上将旧身份合并到新身份:
# 推荐:按访客名称迁移(更简单,名称可在侧边栏看到)
pnpm mdocs visitor migrate --from Alice --to Bob --confirm
# 也支持按 UUID 迁移(精确匹配)
pnpm mdocs visitor migrate --from OLD_ID --to NEW_ID --confirm
# 试运行,查看影响范围但不实际执行
pnpm mdocs visitor migrate --from Alice --to Bob --dry-run
该操作在事务内执行,更新文档所有权,禁用旧访客,并记录审计日志。
查看所有访客
pnpm mdocs visitor list # 默认只看启用的访客
pnpm mdocs visitor list --all # 看全部(含已禁用的)
设计取舍
- **放弃重型「用户体系」**换低准入;跨端能力用「可选密码」补齐,而不是一上来就上完整账号平台
- HttpOnly Cookie 日常鉴权:服务端重启不轻易丢当前浏览器会话
- 可以匿名浏览:不注册也能看到公开域的公开文档
- 恢复码:服务早期 Cookie-only 身份的自助找回;密码普及后降为兼容能力