HMAC 登录与手机号盐实践
从两个带登录/订阅的站点实践里提炼的机制与经验,不含任何密钥、盐值、站点 ID。
#一、HMAC 令牌登录
- 登录态用一个
AUTH_SECRET(HMAC 签名密钥)签发的令牌承载。 - 改
AUTH_SECRET= 所有人被强制重新登录。这是「一键登出全站」的实现方式。
#二、手机号摘要盐必须全链路一致
- 报名/白名单类站点,不存明文手机号,只存手机号摘要(用
PHONE_SALT做加盐哈希)。 - 铁律:导入报名名单时用的盐,必须和线上登录校验用的盐是同一个值。
- 否则名单里的人一个都登不上——导入侧算出的摘要和登录侧算出的摘要对不上。
- 盐值本身属敏感凭据,环境变量里配、离线留档,绝不进代码/仓库/文档正文。
- 名单导入是一条独立脚本:
PHONE_SALT=<盐> node import-attendees.mjs 报名表.csv > attendees.sql,再灌进数据库。
#三、Turnstile 人机验证的密钥模型
- Cloudflare Turnstile 有两把配套的值:
- sitekey:公开,可直接写进前端页面;
- secret:私密,只在服务端校验时用,写进 Worker Secret / 环境变量,可在 Cloudflare 面板随时查看/轮换。
- 前端拿 sitekey 渲染小组件、拿到 token;服务端用 secret + token 调 Turnstile 校验接口确认是真人。
#四、订阅站的 double opt-in(双重确认)
- 邮件订阅走 double opt-in:用户提交邮箱后,先发一封确认邮件,用户点确认链接后才真正入库。
- 确认链接里带一个用
SUBSCRIBE_SECRET(HMAC 密钥)签发的 token,服务端验签确认链接未被伪造/篡改。 - 好处:避免被人拿别人邮箱恶意订阅,也提升送达侧的列表质量。
#五、双云主备架构
- 同一个站可以主备双云部署:一套主入口(如 Vercel + 托管 Postgres),一套备用(如 Cloudflare Workers + D1)。
- 两边的
AUTH_SECRET/PHONE_SALT等关键变量取同一套值,名单和登录态才能两边通用、随时切换。 - 泛解析(
*.域名泛 CNAME)到主入口后,新增子域不用再动 DNS。
#六、通用要点
- 所有 HMAC 密钥、盐值属 sensitive 凭据:环境变量里配、离线留一份备份,绝不写进代码、仓库或文档正文。
- 改密钥/盐是有破坏性语义的操作(强制登出 / 名单失效),改前想清楚影响面。
来源:配置信息/FDEC2026选座站密钥.md;配置信息/ai-daily-订阅站凭据.md(整理于 2026-08-18)