Files
huajishe-tts/docs/texas/08-user-login.md
e2hang 04d0af515c feat: 登录系统落地 + 踢人修正 + 单房间约束 + 权限收口
问题8 登录系统:
- node:sqlite 账号存储(scrypt 哈希 + HMAC 签名 token),preset admin 改为 e2hang/evan1115
- /api/auth/register|login|me,me 返回 room 供重联
- 网关拦截 create/join 需登录(401),列表保持开放

踢人逻辑修正(问题2 延伸):
- kickMove 真正释放座位(folded=false, name=null)而非锁死
- war/mill 去掉永久封禁语义

管理员越权:管理员 token 可删任意房间、踢任意房间内的人

单房间约束(用户新需求):
- 同一用户同时只能在一个房间,create/join 他房返回 409
- 踢人后若房间仅剩踢人者则自动解散并释放其记录(修复 2 人局踢光对手后被困 409)
- 陈旧房间记录兜底清理

UI 清理:移除"改名"按钮与"你的名字"输入框;删除房间按钮仅房主/管理员可见

docs: 新增 12-auth-kick-single-room.md 汇总本会话全部需求/根因/修复/边界测试

Co-Authored-By: Claude (CodeBuddy) <noreply@codebuddy.ai>
2026-08-25 14:13:59 +08:00

3.3 KiB
Raw Permalink Blame History

问题 8通用用户登录系统名称 + 密码身份)

需求

“可不可以做一个用户登录,用户设置名称和密码然后以这个身份加入。” 即:用户在客户端注册/登录一个账号(名称 + 密码),之后以该身份创建/加入房间。 —— 这是一个跨房间、跨对局的持久身份,区别于当前“每次改名只影响单个房间”的 playerName

现状

  • 当前身份仅为 App.playerNamelocalStorage 里的随机名,可随时改), 进入房间时作为 playerName 传给 lobby joinMatch无密码、无账号、无服务端校验
  • boardgame.io 的 lobby joincredentialsserver 生成的随机串)鉴权,与“用户密码”无关。

拟采用方案(轻量账号系统,复用现有 server

后端(packages/server

新增账号存储 + 登录/注册端点(挂在 /api/auth/...),因 server 是 InMemory重启丢数据 账号表也用内存 Map可接受如需持久化见下方决策点

// 内存表username -> { passwordHash, salt }
const accounts = new Map<string, { hash: string; salt: string }>();
  • POST /api/auth/register body { username, password } 校验用户名长度/字符;用 crypto.scrypt 加盐哈希;已存在则 409。
  • POST /api/auth/login body { username, password } 校验哈希;成功返回 { token }(用 HMAC/签名 JWT 或简单签名串,含 username + 过期时间)。
  • (可选)GET /api/auth/me 用 token 回显 username。

说明:本项目的“身份”主要用于进房时的名字与一致性,不需要 OAuth 级安全。 哈希存储是基本卫生不存明文密码。token 用 crypto 签名即可,不必引入 jsonwebtoken 依赖。

前端(apps/web + packages/ui

  • App.tsx 顶部加“登录/注册”栏(登录态存 localStorage{ username, token })。
  • 登录后,把 username 作为进入房间时的 playerName(替换当前的随机名/手输名)。
  • 房间列表 LobbyRoomListplayerName 改为取“已登录账号名”(未登录则退回原有输入/随机名)。
  • 退出登录清除本地 token。

与问题 1/2 的耦合

  • 登录身份 → playerName → 进房 joinlobby metadata name
  • 改名(问题 1登录用户是否允许改名建议登录用户以账号名为准,房间内改名仅作用于本房间显示(保持现有 rename move 语义)。
  • 房主判定(问题 2账号体系与“房主”是两回事房主仍是房间创建者metadata createdBy),与登录名无关。

决策点(需用户确认)

  1. 账号持久化:内存(重启即丢,与现有 InMemory 房间一致vs 落盘FlatFile/JSON。建议先内存后续可加。
  2. 安全强度休闲局域网场景scrypt + 签名 token 是否足够?还是用户期望真正的会话/多端?
  3. 是否强制登录:允许匿名(随机名)进入,还是必须登录才能创建/加入房间?建议允许匿名,登录为可选增强。

验证

  • 注册 → 登录拿 token → 以该名进房,房间列表 pill 显示账号名。
  • 错误密码登录失败;重复注册 409。
  • 登录态在刷新后保留localStorage