feat: 用户名登录——一账号一个牧场,登录后改 URL 也进不了别人的档
多用户之前是「知道牧场名就能玩」:?farm=boss 直接进别人家里。 现在网页端用用户名登录(用户选择:不设密码、一账号一个牧场, 用户名即身份——互信小圈子模型,防的是随手改 URL,不是蓄意攻击)。 * 新增 farm/server/auth.py:HMAC-SHA256 签名的 HttpOnly Cookie (sf_auth,30 天,恒时比较防篡改)。密钥存 <save_dir>/secret.key, 重启不掉线,也不用建表存 token。 * app.py 三个认 ?farm= 的地方(session_of / SSE / POST /api/farms) 统一规则:有 Cookie 强制本人的牧场(?farm=/X-Farm-Id 被忽略), 无 Cookie 保持旧语义——bot/TUI/CLI 脚本零改动照常工作。 * 新路由:POST /api/login(全局 token 照常把它挡在门外)、 POST /api/logout、GET /api/me(刻意不 guard:首屏只问"登录没")。 * 网页:移除牧场名输入框,改为登录遮罩 + 用户徽章 + 退出按钮; 首屏先 whoami() 再决定连接还是弹登录。 测试 +13:Cookie 伪造/过期/跨密钥/垃圾串/非法用户名/密钥跨重启复用/ session_of 优先级(starlette Request 用 scope dict 直接构造,不需要 httpx)9 项纯逻辑档 + 4 项 TestClient 档。528 项 OK(skip 39)。 真机验收 16/16:登录/HttpOnly/?farm= 被忽略/动作落自己牧场/篡改 退回未登录/退出/非法名 400;跨重启 Cookie 仍有效且进度保留。
This commit is contained in:
1 parent
d1692d7b10
commit
698a5e497a
7 files changed
+391
-215
No files matched your search
@@ -28,3 +28,32 @@
|
||||
弹层实现。
|
||||
- 一个布尔标志被两个子系统共用时,其中一个高频清零,另一个低频读取——
|
||||
低频的那个等于瞎了。存盘依据必须由"成功的写入"来清。
|
||||
|
||||
## 2026-09-23 用户名登录(多用户)
|
||||
|
||||
- 用户要求「添加多用户的 需要使用用户名登录」;AskUserQuestion 确认:
|
||||
**仅用户名**(不设密码)+ **一账号一个牧场**(用户名即牧场名)。
|
||||
- 新增 `farm/server/auth.py`:`LoginManager` 签发/校验 HMAC-SHA256 签名的
|
||||
HttpOnly Cookie(`sf_auth`,30 天,SameSite=Lax)。Cookie 值 =
|
||||
`base64("用户名|过期时间") + "." + hmac`,验签 `hmac.compare_digest`。
|
||||
密钥 32 字节存 `<save_dir>/secret.key`(0600)——**重启不掉线**,无需建表。
|
||||
- `app.py`:新增 `POST /api/login`(guard 照常检查全局 token)、
|
||||
`POST /api/logout`、`GET /api/me`(刻意不 guard,首屏探测用);
|
||||
`_Services` 加 `auth` 字段与 `user_of()`;**三个认 ?farm= 的地方全部改为
|
||||
「有 Cookie 强制用自己的牧场」**:`session_of`(?farm=/X-Farm-Id 被忽略)、
|
||||
SSE `/api/stream`、`POST /api/farms`。无 Cookie 的脚本/AI/CLI 保持旧语义
|
||||
(互信小圈子,`?farm=` 不受影响),bot/TUI 零改动。
|
||||
- `webui.py`:移除「牧场名」输入框和「进入牧场」按钮,改为登录遮罩
|
||||
(`#loginmask` 复用 `.mask/.pick` 样式)+ 用户徽章 `#who` + 退出按钮;
|
||||
JS 先 `whoami()` 再决定 `connect()` 还是弹登录;令牌输入框保留
|
||||
(change 时重连)。farmName() = 登录用户。
|
||||
- 测试 +13:`LoginCookieTestCase` 9 项纯逻辑(伪造/过期/跨密钥/垃圾串/非法名/
|
||||
密钥复用/session_of 优先级——starlette Request 可直接用 scope dict 构造,
|
||||
不需要 httpx)+ AuthTestCase 4 项 TestClient 档(照例 skip)。
|
||||
门禁 528 项 OK(skip 39),ruff/pyright 全绿。
|
||||
- 真机验收 16/16:登录/Cookie/HttpOnly/?farm= 被忽略/动作落自己牧场/
|
||||
篡改退回未登录/退出/非法用户名 400/首页元素。跨重启:secret.key 复用,
|
||||
Cookie 仍认 carol、显式 save 后作物也在。
|
||||
- 教训:幂等补丁脚本里 `new == ""` 时 `if new in text` 恒真,会误报 ALREADY
|
||||
跳过删除类替换(这次是删全局 Enter 监听那行,靠核对输出抓回来)。
|
||||
删除类编辑别走补丁脚本,直接用 Edit 工具。
|
||||
Reference in new issue
Block a user