feat(M1): 认证与用户管理 — 双通道登录、cookie 会话、用户 CRUD 与真实系统账号对接

认证:
- 图形验证码 GET /auth/captcha(内置 PNG 渲染,零第三方依赖)
- 外部用户 OTP 双通道:DB 存储(otp_codes)使邮件与 CLI 共用同一验证码/冷却/失败限速
- 管理员 bcrypt 登录 + 连续失败限速锁定;admin/forgot + admin/reset 邮件重置(SMTP 或日志)
- cookie 会话(HttpOnly/SameSite)、me/logout、admin/user 鉴权中间件

用户管理(admin):
- CRUD + disable/enable/extend/delete,对接 system 层真实 useradd/usermod/userdel/passwd
- system 层三执行模式:dry-run(默认,安全)/ direct(容器/测试用户)/ sudo(生产 sudoers 白名单)
- Exists 系统账号一致性检查;deploy/sudoers.example 白名单模板
- 关键操作接入 append-only 审计

其他:
- CLI user otp 改 DB store,与邮件通道真正对齐
- 容器镜像补 shadow(alpine 无 useradd);Makefile VERSION 0.2.0-m1
- 测试:auth/service 单测 + api httptest 集成 + 容器内真实系统账号端到端验证
This commit is contained in:
2026-08-29 23:40:20 +08:00
parent ae45aba607
commit 630d240dc0
32 changed files with 2923 additions and 188 deletions
+8 -1
View File
@@ -8,6 +8,7 @@
[app]
name = "ws_usernode"
env = "development" # development / production
base_url = "http://127.0.0.1:8080" # 对外访问地址(邮件重置链接等)
[server]
listen = "127.0.0.1:8080" # 生产建议 0.0.0.0:8080 并置于反向代理后
@@ -30,6 +31,11 @@ audit_retention = "720h" # 审计保留 30 天,保留前先归档
otp_ttl = "10m" # OTP 验证码有效期
otp_cooldown = "60s" # OTP 发送冷却
[auth]
max_login_failures = 5 # 管理员登录连续失败阈值,达到后锁定
lock_duration = "15m" # 锁定持续时间
captcha_ttl = "5m" # 图形验证码有效期
[smtp]
host = "" # 留空则禁用邮件(OTP 仍可用 CLI 通道获取)
port = 587
@@ -38,7 +44,8 @@ password = ""
from = "usernode@example.com"
[system]
sudo = false # 开发环境 false = dry-run(只打印不执行);生产 true 经 sudo -n 执行
sudo = false # 生产 true经 sudo -n 执行 useradd/usermod/userdel/passwd(需 deploy/sudoers
dry_run = true # 开发演练 true:只打印计划命令不执行;false 且 sudo=false 时直接执行(容器/测试用户验证)
user_prefix = "ext_" # 外部用户系统账号统一前缀
group = "external" # 外部用户统一组
shell = "/bin/sh" # 默认 shell