docs: 归档任务 #50

This commit is contained in:
chengma
2026-08-09 13:37:23 +08:00
parent 0a7db404a1
commit 771e2ee616
@@ -0,0 +1,86 @@
# 50 Admin:实现首次管理员初始化与网页登录
- 类型:需求
- 父级大工单:#14
- 所属 MVP / 版本:#15 / MVP
- 状态:已完成
- 日期:2026-08-09
- Gitea 工单:<http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/50>
## 背景与目标
Admin 原有全部网页都可匿名访问,也没有管理员初始化、登录或退出能力。本任务
建立最小且完整的网页登录边界:首次运行由操作员创建唯一的首位管理员,随后
所有业务网页必须凭服务端 Session 访问,同时保持 Client API 的现有调用方式不变。
## 最终方案
- 新增 v6 迁移,在末尾追加 `users` 和 `web_sessions`,未改写 v1–v5;用户名
使用不区分大小写的唯一约束,角色和状态使用固定值约束。
- `/setup` 仅在用户表为空时开放;创建管理员前在写事务内再次检查,两个并发
初始化请求最多一个成功。入口一旦关闭,即使账号以后禁用也不会重新开放。
- 密码使用 bcrypt 默认成本哈希,服务层校验至少 8 个字符和 bcrypt 的 72 字节
上限;数据库、页面及日志均不保存或回显明文密码。
- 登录成功生成 32 字节密码学随机 Token,浏览器 Cookie 保存原文,数据库只保存
SHA-256。Session 固定 12 小时有效,退出和账号禁用会使旧 Session 失效。
- 认证 Cookie 使用 `HttpOnly`、`SameSite=Lax`、`Path=/`,HTTPS 请求自动增加
`Secure`;登录后的 `next` 只接受本站绝对路径,阻止开放重定向。
- Web 公开页和业务页都经过 CSRF;认证中间件只挂业务网页路由组。Client API
继续注册在独立路由组,不要求网页登录 Cookie,也不经过浏览器 CSRF。
- 增加独立初始化页和登录页;业务导航显示当前用户名,并用 POST 表单退出。
实际实现与工单确认方案一致。采购员管理、密码重置和登录限速留给 #51,Client
API Key 认证留给 #52,本任务没有扩大范围。
## 改了哪些
- `admin/repository/db.go`、`admin/model/model.go`、`admin/repository/user.go`:
v6 数据结构、用户与 Session 数据访问及初始化事务。
- `admin/service/auth.go`:首次初始化、bcrypt 密码校验、登录认证、Session 哈希与退出。
- `admin/handler/web/auth.go`、`admin/handler/web/web.go`:公开认证页、业务页中间件、
Cookie、本站回跳和退出路由。
- `admin/templates/auth/`、`admin/templates/partials/header.html`、
`admin/static/css/app.css`:初始化、登录和已登录导航界面。
- `admin/auth_integration_test.go`、`admin/handler/web/auth_test.go`、
`admin/service/auth_test.go`、`admin/repository/migrate_test.go`、`admin/main_test.go`:
迁移、并发、安全属性、HTTP 完整流程和回归测试。
- `docs/admin/03-data-model.md`:将 v6 用户与 Session 模型从规划更新为已实现。
## 验收结果
| 验收标准 | 结果 |
|---|---|
| v6 可从全新库和历史结构升级,且未改写旧迁移 | 通过 |
| 首次初始化并发请求最多创建一个管理员 | 通过 |
| 初始化完成后 `/setup` 永久关闭 | 通过 |
| 密码只保存 bcrypt 哈希,错误凭据统一提示 | 通过 |
| Session 原文不入库,固定 12 小时过期 | 通过 |
| 退出、过期和账号禁用后旧 Session 失效 | 通过 |
| Cookie 具备 HttpOnly、SameSite、Path 和 HTTPS Secure 属性 | 通过 |
| 登录回跳不能跳往外部网站 | 通过 |
| 所有 Web POST 均经过 CSRF | 通过 |
| Client API 不经过网页登录与浏览器 CSRF | 通过 |
| 1366×768 初始化、登录及已登录导航布局 | 通过 |
| Go 1.23.0 全量检查 | 通过 |
## 测试
- 执行的命令:
```powershell
cd D:\chengma\cmautobuy\admin
gofmt -l .
go vet ./...
go build ./...
go test ./... -count=1
```
- 结果:Go 版本为 `go1.23.0 windows/amd64`;全部通过,`gofmt -l .` 无输出。
- 浏览器验证:使用隔离的临时数据库,在 1366×768 完成 `/setup` 初始化、`/login`
登录并进入 `/shopee`;表单标签、密码框、提示、用户名和退出按钮均正常。
- **没验证到的部分**:没有在真实 HTTPS 服务上手工检查浏览器 Cookie,`Secure`
属性由带 TLS 请求的单元测试覆盖;没有触发真实采集或采购。
## 相关提交
- `0a7db40` feat: 实现 Admin 首次初始化与网页登录 (#50)