Files
cmautobuy/docs/task/50-admin-首次管理员初始化与网页登录.md
T
2026-08-09 13:37:23 +08:00

87 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)