docs: 归档任务 #50
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user