Files
yunzerwebsiteallinone/.trae/documents/fix-login-infinite-loop.md
T
2026-11-05 18:28:46 +08:00

3.2 KiB
Raw Blame History

修复登录无限循环(登录成功后弹回登录页)

Context(问题与证据链)

用户反馈:登录成功后又回到登录界面,无限循环。排查已确认(含用户亲证):

用户确认的现象

  • 登录页地址栏为 api.yunzer.cn(远程线上认证中心,非本地 9000)
  • 登录后见过「选择要进入的企业」界面(hero920103 绑定 2 家企业),选完企业后又弹回登录页

数据库证据(go-platform 库)

  • hero920103 = identity_id 2(李志强),绑定两家企业(tid=1、tid=2)→ 登录必走"待选企业"分支
  • yz_auth_session:18:09~18:12 连续 4 条会话被踢(revoked=1, revoke_reason='kicked');最新会话 id=386(18:18:29,tid=2,client_id 为空)
  • 18:24:42 登录日志(id=218,user_id=1)与 hero920103 实际 identity_id=2 不符 → 该日志由远程旧版代码写入(字段语义不同),且 IP=127.0.0.1/::1 符合"远程 nginx 反代回环"特征

代码机制(go/services/auth/session.go L61-134)

  • CreateSession 按 identity_id 全局统计活跃会话,超 MaxSession 即踢最旧会话(kicked),不区分 tid/client/服务实例
  • 登录 → 远程建会话 → 企业选择 → 新会话又创建 → 互踢 → authorize 发现会话已吊销 → 送回登录页 → 再登录 → 无限循环
  • 远程为旧版代码(字段错位可证),其企业选择后的会话处理存在缺陷,无法本地修复

修复方案

第一步:本地开发认证切换到本地 9000 实例(核心修复)

修改 backend/.env.development:

VITE_AUTH_BASE='http://127.0.0.1:9000/auth'

本地 9000 已注册全套认证端点(/auth/login、/auth/authorize、/auth/token、/auth/userinfo、/auth/switch-tenant,见 go/routers/auth/auth.go),且为最新代码(企业选择、cookie、PKCE 逻辑完整)。

第二步:配套校验与清理

  1. 核对 yz_auth_client 表 yz-backend 的 redirect_uris 白名单包含 http://127.0.0.1:4401/auth-callback.html(不匹配则用 MySQL MCP 补登)
  2. 清理脏数据:将 hero920103(identity_id=2)名下 revoked=0 的旧会话标记 revoked=1(reason='cleanup'),避免旧会话占用互踢名额
  3. 重启 Vite dev server 使 env 生效
  4. 验证本地登录页 HTML 表单嵌入 client_id(curl 抓取确认,防止空 client 会话再现)

第三步:端到端验证

  1. 无痕窗口(避免残留 localStorage token/userInfo)访问 http://127.0.0.1:4401
  2. 完整走:跳本地登录页 → 输入 hero920103 → 企业选择(展示 2 家)→ 选 tid=2 → 回跳 auth-callback → 进入工作台,无循环
  3. MySQL MCP 复查 yz_auth_session 无异常互踢
  4. 登录恢复后,验证原任务功能:apps/oa/schedule 日历按 hero920103 排班显示上班(绿)/休息(橙)背景(后端 /backend/oa/scheduling/my 已就绪)

涉及文件

  • backend/.env.development(唯一代码修改:VITE_AUTH_BASE 指向本地)
  • 数据库:yz_auth_client(白名单核对)、yz_auth_session(脏数据清理)
  • 不改 Go 代码(互踢规则是合理安全设计;根因是开发环境认证指向了旧版远程中心)