外观
账号与登录
管理端的鉴权配置与操作:静态 admin token、管理员账号体系、Cap 人机验证、会话管理。
两种 admin 凭据
管理面(/admin/* 与 /ui/*)在 require_admin 单入口无差别接受两种 Bearer 凭据:
| 凭据 | 适用 | 来源 |
|---|---|---|
| 静态 admin token | 脚本、自动化、curl | control-server.toml 的 [server] admin_token,或 DN42_CONTROL_ADMIN_TOKEN |
| 账号会话令牌 | 浏览器登录 | POST /control/v1/auth/login 签发 |
fail-closed:admin_token 未配置时管理面整体 403——不会因缺配置而敞开,账号登录同样锁定。
审计日志区分两种凭据的操作者:静态 token 记 actor 为 admin,账号会话记用户名。
账号体系
- 密码用 argon2id 散列入库(
admin_users表)。对不存在的用户名也执行一次对照校验,抹平时间侧信道。 - 会话令牌随机生成,DB 只存 sha256(
admin_sessions表),TTL 默认 24 小时。改密立即吊销该账号的全部存活会话(含当前会话)。 - 登录必须通过 Cap 服务端硬校验。三项 Cap 配置不齐时登录一律
400(fail-closed),静态 token 不受影响。 - 登录限速:同用户名或同来源 IP 连续凭据失败 5 次,进入 15 分钟封禁窗口,返回
429;登录成功清零计数。限速状态在控制面进程内。
首个管理员
配置 [auth] bootstrap_admin,值为 user:password。控制面启动时尝试引导(app/services/admin_accounts.py 的 bootstrap_from_env):
- 仅当
admin_users表为空时创建账号;表非空则跳过。 - 幂等:配置残留不会覆盖已改过的密码。
- 值不是
user:password形态时记错误日志并跳过,不中断启动。
引导完成后建议改密,并清掉该配置项。
登录与改密
bash
# 登录(Web 界面内置此流程;直接调 API 需自行取得 Cap token)
curl -s -X POST https://api.natlan.io/control/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username": "...", "password": "...", "captcha_token": "..."}'
# → {"token": "...", "expires_at": "..."}
# 改密(仅账号会话令牌可调,静态 admin token 返回 403)
curl -s -X POST https://api.natlan.io/control/v1/auth/password \
-H "Authorization: Bearer <会话令牌>" \
-H 'Content-Type: application/json' \
-d '{"old_password": "...", "new_password": "..."}'请求体的 token 字段 captcha_token 与历史名 turnstile_token 等价收取。新密码至少 8 字符。改密成功返回 204,随后所有会话失效,前端需重新登录。
状态码
| 码 | 含义 |
|---|---|
400 | 人机验证失败。detail 恒为 turnstile verification failed |
401 | 凭据无效。detail 恒为 invalid credentials(用户不存在与密码错误统一文案,防枚举) |
403 | 服务端未配置 admin token(fail-closed);或用静态 token 调改密 |
429 | 尝试过多。detail 恒为 too many attempts |
错误 detail 措辞是与前端锁死的稳定契约,改动即破坏兼容。
配置清单
| 项 | TOML 键 | 环境变量 |
|---|---|---|
| 静态 admin token | [server] admin_token | DN42_CONTROL_ADMIN_TOKEN |
| Cap 实例地址 | [auth] cap_api_endpoint | DN42_CONTROL_CAP_API_ENDPOINT |
| Cap site key | [auth] cap_site_key | DN42_CONTROL_CAP_SITE_KEY |
| Cap secret key | [auth] cap_secret_key | CAP_SECRET_KEY |
| 首账号引导 | [auth] bootstrap_admin | DN42_CONTROL_BOOTSTRAP_ADMIN |
| 会话 TTL | [auth] session_ttl_seconds | DN42_CONTROL_SESSION_TTL_SECONDS |
完整配置面见 Control Server 配置。
Cap 实例的两个前置
人机验证用的是自托管 Cap 实例(与 auth-server 共用同一实例、同一 widget)。两件事必须配对:
- Cap 实例的 CORS 白名单必须包含控制台的访问域名,否则前端拿不到有效 token,登录一律
400。 - 控制面侧的
cap_api_endpoint生产上应走容器网内地址,避免服务器验证自己签的票要绕一圈公网与 CDN。
Cap 实例本身随控制面整栈部署,见 控制面部署。