+73
-43
@@ -1,56 +1,86 @@
|
||||
# web/auth — iAOP 登录认证 + 用户/角色管理
|
||||
# web/auth — iAOP 登录页与本地账号会话管理(issue #150 / PRD 8.2)
|
||||
|
||||
issue #134 / PRD 8.2 认证鉴权。纯静态(无构建链)Demo 级实现:
|
||||
登录页 + 会话管理 + 用户/角色管理 + 三级 RBAC 门控 + OIDC SSO 预留。
|
||||
登录认证是配置台/驾驶舱写操作的入口闸门。未登录用户不可访问写操作(PRD 8.2)。
|
||||
|
||||
## 文件
|
||||
## 组成
|
||||
|
||||
```
|
||||
web/auth/
|
||||
├── auth.js # 共享库:用户 CRUD(加盐 SHA-256)/ 会话 / 权限矩阵 / 审计 / OIDC 配置点
|
||||
├── login.html # 登录页(本地账号;配置 OIDC 后出现 SSO 入口)
|
||||
├── users.html # 用户/角色管理页(仅 admin)+ OIDC 配置 + 审计日志查看
|
||||
├── users.js # 管理页逻辑
|
||||
└── README.md
|
||||
```
|
||||
**前端(纯静态)**
|
||||
- `login.html` / `auth.css` / `auth.js` — 深色主题登录页,对接 `/auth/login`、`/auth/me`;
|
||||
`auth.js` 导出 `IAOP_AUTH.requireLoginElseRedirect()` 供其它页面做路由守卫。
|
||||
|
||||
## 使用
|
||||
**后端(core/auth,纯标准库)**
|
||||
- `users.py` — `User` 模型 + `PBKDF2-HMAC-SHA256` 密码哈希(盐 16B / 迭代 200000,
|
||||
OWASP 2023 量级)+ `UserStore`(内存,可换 PG 后端)。恒定时间校验防时序侧信道。
|
||||
- `session.py` — HMAC 签名会话 token(`<uid>.<expire>.<sig>`),HttpOnly cookie `iaop_session`。
|
||||
- `postgres_users_schema.py` — PostgreSQL `users` 表 DDL(`BIGSERIAL id` / `username UNIQUE` /
|
||||
`password_hash` / `role CHECK(readonly|engineer|admin)` / `active` / 时间戳),对齐 #30。
|
||||
- `auth_api.py` — 认证 HTTP 端点(`POST /auth/login` `POST /auth/logout` `GET /auth/me`)+
|
||||
`require_auth` / `can_write` 守卫(未登录 401、readonly 写 403,PRD 8.2)。
|
||||
- `tests/test_auth.py` — 单元测试。
|
||||
|
||||
## 跑测试
|
||||
|
||||
```bash
|
||||
# 从 web/ 根目录起服务(studio 集成依赖 ../auth 相对路径)
|
||||
cd web && python -m http.server 8083
|
||||
# 打开 http://127.0.0.1:8083/auth/login.html
|
||||
# 仓库根目录
|
||||
python -m pytest core/auth/tests/test_auth.py -v
|
||||
# 或无 pytest:
|
||||
python core/auth/tests/test_auth.py
|
||||
```
|
||||
|
||||
首次运行内置管理员 **admin / admin123**(登录后请立即在用户管理页改密)。
|
||||
未登录访问 `web/studio/`(模板配置台)会自动跳转登录页,登录后按会话角色
|
||||
应用三级 RBAC(Viewer 只读 / Editor 配置 / Publisher 发布+回滚)。
|
||||
## 冒烟(认证服务)
|
||||
|
||||
## 语义对齐
|
||||
|
||||
| 能力 | 对齐后端 |
|
||||
|------|----------|
|
||||
| 角色 readonly / engineer / admin,动作 view / edit / publish / manage | `core/template-console/rbac.py`(Resource/Action/RoleKind) |
|
||||
| 用户数据(username/role/enabled/salt/hash) | `core/data-bus/config/postgres.template.yaml` users/permissions 表(Demo 落 localStorage,后端 HTTP 就绪后替换 `UserStore` 读写即可) |
|
||||
| 写操作审计(时间/操作人/动作/资源/原因) | `template_registry._log` 风格 + `prompts.drain_audit` 语义 |
|
||||
| OIDC 配置点(issuer/client_id/redirect_uri) | PRD 8.2 双轨:未配置走本地账号,配置后登录页出现 SSO 入口(标准授权码流程 authorize URL 已可生成;令牌换会话的后端端点待企业 IAM 就绪后对接) |
|
||||
|
||||
## 各前端页面接入方式
|
||||
|
||||
```html
|
||||
<script src="../auth/auth.js"></script>
|
||||
<script>
|
||||
var session = Auth.requireAuth("../auth/login.html"); // 未登录 → 跳登录页
|
||||
if (session) { /* Auth.can(session.role, "edit" | "publish" | "manage") 门控写操作 */ }
|
||||
</script>
|
||||
```bash
|
||||
python -m core.auth.auth_api
|
||||
# → iAOP AuthAPI on http://127.0.0.1:8088(初始管理员 admin / change-me-now,生产必须改密)
|
||||
```
|
||||
|
||||
`web/studio` 已接入(未登录不可进入,写操作按会话角色门控,发布/回滚落审计);
|
||||
auth.js 缺失时 studio 降级为手动角色切换演示,向后兼容。
|
||||
```bash
|
||||
curl -s -X POST http://127.0.0.1:8088/auth/login -H 'Content-Type: application/json' \
|
||||
-d '{"username":"admin","password":"change-me-now"}' -c /tmp/c.txt
|
||||
curl -s http://127.0.0.1:8088/auth/me -b /tmp/c.txt
|
||||
```
|
||||
|
||||
## 安全说明(Demo 边界)
|
||||
## 前端冒烟
|
||||
|
||||
- 密码加盐 SHA-256(Web Crypto)存储,不落明文;会话 token 8 小时过期,
|
||||
账号禁用/删除即时失效;
|
||||
- localStorage 存储仅用于无后端 Demo;生产部署需由后端接管 users 表
|
||||
(PostgreSQL)与会话签发,本库 API(login/session/can/audit)保持不变。
|
||||
```bash
|
||||
cd web/auth && python -m http.server 8090
|
||||
# 浏览器开 http://localhost:8090/login.html(AUTH_BASE 指向 :8088 见 auth.js)
|
||||
```
|
||||
|
||||
## 角色(对齐 core/template-console/rbac.py)
|
||||
|
||||
| 角色 | 读 | 配置写 | 发布/回滚 |
|
||||
|------|----|--------|----------|
|
||||
| readonly | ✓ | ✗ | ✗ |
|
||||
| engineer | ✓ | ✓ | ✗ |
|
||||
| admin | ✓ | ✓ | ✓ |
|
||||
|
||||
## 安全
|
||||
|
||||
- 永不存明文密码;存储 `pbkdf2_sha256$<iter>$<salt-b64>$<hash-b64>`。
|
||||
- `authenticate` 失败不区分"用户不存在/密码错",防用户名枚举。
|
||||
- token HMAC 恒定时间校验;cookie `HttpOnly; SameSite=Lax`。
|
||||
- 生产必须设置 `IAOP_AUTH_SECRET` 环境变量(多副本共享)并改初始管理员密码。
|
||||
|
||||
---
|
||||
|
||||
## 用户/角色管理页(issue #134 增补)
|
||||
|
||||
- `users.html` / `users.js` / `user_store.js` — 用户列表、角色分配
|
||||
(readonly/engineer/admin)、启用/禁用、重置密码、删除;仅 admin 可访问
|
||||
(守卫复用 `IAOP_AUTH.requireLoginElseRedirect` + role 检查)。
|
||||
- **存储边界**:core/auth 目前只提供 login/logout/me 端点,用户 CRUD 端点尚未提供,
|
||||
故管理数据先落 localStorage(Demo 级;User 字段语义对齐 `core/auth/users.py`),
|
||||
后端补齐 `/auth/users` CRUD 后仅需替换 `user_store.js` 内部读写。
|
||||
- **写操作审计**:用户 CRUD / OIDC 配置 / 配置台发布与回滚均落审计
|
||||
(时间/操作人/动作/资源/原因,`template_registry._log` 风格),users.html 可查看。
|
||||
- **OIDC SSO 配置点(预留,PRD 8.2 双轨)**:users.html 维护 issuer / client_id /
|
||||
redirect_uri;配置后登录页可出现 SSO 入口(`UserStore.oidcAuthorizeUrl()` 生成
|
||||
标准授权码流程 URL)。未配置走本地账号。令牌换会话的后端端点待企业 IAM 就绪后对接。
|
||||
|
||||
## 配置台接入(web/studio)
|
||||
|
||||
`web/studio/index.html` 已引入 `../auth/auth.js` + `../auth/user_store.js`:
|
||||
未登录访问配置台自动跳登录页(PRD 8.2「未登录不可访问写操作」);
|
||||
登录后角色以会话为准(顶栏角色下拉锁定),admin 可一键进入用户管理页;
|
||||
发布/回滚写操作落审计日志。纯静态独立起服务(无 auth.js)时降级为手动角色切换演示。
|
||||
|
||||
Reference in New Issue
Block a user