Skip to content

账号与登录

本文讲管理端的鉴权配置与操作:静态 admin token、管理员账号体系(浏览器登录)、Turnstile 人机校验、会话管理。安全模型的设计依据见 ../internals/security.md,端点契约见 ../reference/api.md

两种 admin 凭据

admin API(/admin/*/ui/*)无差别接受两种 Bearer 凭据(apps/control-server-ts/src/auth.ts:23-48):

凭据适用来源
静态 admin token脚本 / 自动化 / curl主面 wrangler secret put ADMIN_TOKEN;温备面 control-server.toml / DN42_CONTROL_ADMIN_TOKEN
账号会话令牌浏览器(Web UI 登录)POST /auth/login 签发

fail-closedADMIN_TOKEN 未配置时 admin API 整体 403(不会因缺配置而敞开)。审计日志以 principal.identity 区分两种凭据的操作者。

账号体系

  • 密码用 argon2id 散列入库(admin_users 表);对不存在的用户名也执行一次对照校验,抹平时间侧信道。
  • 会话令牌随机生成,DB 只存 sha256(admin_sessions 表),TTL 默认 24h(SESSION_TTL_SECONDS);改密吊销该账号全部会话
  • 登录必须通过 Cloudflare Turnstile 服务端硬校验(失败 400);TURNSTILE_SECRET_KEY 未配置时登录 400(fail-closed)。
  • 登录限速:同用户名或同来源 IP 连续失败 5 次、15 分钟窗口 → 429。主面限速状态落 KV(最终一致),温备面在进程内。

首个管理员:惰性引导

Workers 没有启动期,首个账号在登录时惰性引导(src/routes/auth.ts:95-98):

  1. wrangler secret put BOOTSTRAP_ADMIN,值为 user:passwordsrc/services/adminAccounts.ts:128-141)。
  2. 用该用户名密码走一次正常登录——仅当 admin_users 表为空时创建账号,幂等;表非空时该 secret 不再生效。
  3. 引导完成后建议改密(见下),并可考虑清掉 BOOTSTRAP_ADMIN secret。

登录与改密

bash
# 登录(Web UI 内置此流程;直接调 API 需自行取得 Turnstile token)
curl -s -X POST https://api.natlan.io/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username": "...", "password": "...", "turnstile_token": "..."}'
# → {"token": "...", ...}

# 改密(仅账号会话令牌可调,静态 admin token 不可)
curl -s -X POST https://api.natlan.io/api/v1/auth/password \
  -H "Authorization: Bearer <会话令牌>" \
  -H 'Content-Type: application/json' \
  -d '{"current_password": "...", "new_password": "..."}'

状态码矩阵:400 Turnstile 失败 / 401 凭据无效 / 403 fail-closed(服务端未配置)/ 429 尝试过多。错误 detail 措辞是与前端锁死的稳定契约,改动即破坏兼容。

配置清单

主面(TS)温备面(Python)
静态 admin tokensecret ADMIN_TOKEN[auth] / DN42_CONTROL_ADMIN_TOKEN
Turnstile secretsecret TURNSTILE_SECRET_KEYTOML [auth] 对应项
首账号引导secret BOOTSTRAP_ADMINuser:password同名语义
会话 TTLvar SESSION_TTL_SECONDS(默认 86400)TOML 对应项

完整配置面见 ../reference/configuration.md

Turnstile 域名单:Cloudflare 面板中 Turnstile widget 的允许域名必须包含 Web UI 的访问域名(如 console.natlan.io),否则前端拿不到有效 turnstile token,登录一律 400。