fix(auth): harden WeChat login and explicit identity switching

This commit is contained in:
xsl
2026-10-12 10:07:54 +08:00
parent 0ec5e5dc32
commit d68f841f0e
16 changed files with 1484 additions and 735 deletions
@@ -1,9 +1,11 @@
# 微信登录接入与公网部署说明
更新:2026-10-11。当前环境为 Windows 宿主机 + 内网 WSL。
更新:2026-10-12。当前环境为 Windows 宿主机 + 内网 WSL。
线上状态补充:`https://1me.xajuzi.com/state/` 已部署并配置真实微信凭据,服务器检查记录见 `线上微信登录部署记录-2026-10-11.md`。下文的内网缺配置说明针对本机开发环境。真实微信授权尚待客户端验证。
2026-10-12 白名单复测已通过,基础凭据有效。最新修正和真机验证步骤见[微信登录联调记录](微信登录联调-2026-10-12.md)。已有本机用户可从「我的报告」→「切换登录方式」进入微信登录;微信会话失效不会自动恢复为本机账号,两个账号的报告不自动合并。
## 结论与当前阻碍
已完成微信网页授权代码,但**没有完成真实微信账号联调**。当前未配置 `WECHAT_APP_ID`、`WECHAT_APP_SECRET`、`PUBLIC_BASE_URL`,也没有可验证的公众号网页授权域名配置。内网 `http://192.168.3.25:8080/` 不能作为本次正式授权部署地址。因此本地启用「本机浏览器登录」,不会模拟微信登录成功。
+53
View File
@@ -0,0 +1,53 @@
# 微信登录联调:2026-10-12
站点:`https://1me.xajuzi.com/state/`;服务器:`ubuntu@1me.xajuzi.com`。
## 白名单与凭据
- 用户再次确认已将服务器出口 IP `49.233.222.47` 加入公众号 IP 白名单。
- 从生产服务正在运行的进程环境读取凭据,在服务器调用微信 `cgi-bin/stable_token`,使用 `force_refresh:false`,未强制刷新已有令牌。
- 返回有效 `access_token`,未返回 `40164`;复测剩余有效时间为 7168 秒。已确认该配置的 AppID 与 `wx645d9a7573f1fe9a` 一致,AppID/AppSecret 校验通过。
- 密钥继续留在 root 私有文件 `/etc/juzi/wechat.env`(600);服务监听 `127.0.0.1:8080`,站点地址包含 `/state/`。没有将密钥或令牌写入代码、日志、文档或前端。
- 基础接口令牌成功不等于真实用户网页授权成功;后者仍要验证公众号网页授权权限、网页授权域名以及真实微信客户端回调。
## 本轮修正
1. 「我的报告」增加「切换登录方式」,复用现有登录页。已有本机用户可以进入微信登录;重新勾选协议后才发起授权。只切换所选账号,不自动合并、迁移或删除报告;返回可继续原会话。
2. 本地只记录最近一次有效登录的方式(`juzi.auth.kind.v1`),不存 OpenID 或微信令牌。微信会话失效后,不能用遗留本机随机凭据自动登录另一个账号;需显式重新选择登录方式。同一微信重新登录仍对应同一服务端账号。
3. 微信返回错误或返回后 Cookie 未保留时,保持登录页并说明原因,不允许用本机自动恢复掩盖失败。处理后移除 URL 的一次性登录结果参数,避免刷新后反复显示旧错误。
4. 服务端拒绝微信响应中的无效 OpenID、异常 HTTP 状态等错误响应;网络失败、平台失败、state 校验失败均不签发会话。
5. 增加 `[auth/wechat]` 运行事件:`callback_rejected`、`exchange_failed`、`login_success`。仅记录错误种类、微信数值错误码、HTTP 状态和是否新账号;不记录 code/state、Cookie、OpenID、密钥或令牌。
## 自动验证
```bash
node h5/test/accounts.js
node h5/test/wechat-browser.mjs
node h5/test/report-persistence.mjs
node h5/test/recommendation.js
node h5/test/analyze-timeout.js
H5_BASE_URL=https://1me.xajuzi.com/state/ node h5/test/wechat-production.mjs
```
- 账号测试覆盖协议、同源校验、state 绑定/一次性使用、跨账号隔离、账号持久化;新增无效 code、空响应、非字符串 OpenID、HTTP 500 和网络错误均拒绝登录的验证。
- 真实 HTTPS + `/state/` 浏览器测试仅模拟微信上游,覆盖本机→微信→本机显式切换、原报告保留、同一微信跨两个独立浏览器读取同一报告、另一微信无法读取、Cookie 丢失不串号、失败提示不被本机自动恢复掩盖。
- 报告保存与回看、前后台一致性、126 个推荐用例及检测超时回归通过;不调用收费 Face++。
- 公网预检脚本只使用刻意无效的 code,验证授权 URL/绑定 Cookie、真实微信拒绝无效换码、state 防重放、同源与协议校验、匿名报告拒绝及后台保护;不创建微信身份,不表示真人授权成功。
## 真实微信验收与排查
目前尚不能将模拟授权和基础凭据通过视为真人登录已完成。服务器与无头浏览器不能替用户产生真实微信授权 code,也不在生产环境伪造微信身份。
1. 手机微信内打开 `https://1me.xajuzi.com/state/`,不要选择「在浏览器打开」。
2. 若已有本机登录,进入「我的报告」→「切换登录方式」;勾选协议,点击「微信登录」。
3. 登录后进入「我的报告」,身份提示应为「同一微信账号可跨手机查看」。首次使用微信身份时列表可能为空:本机账号历史报告不会自动合并。
4. 同一微信重新登录或换另一台手机查看,账号和已保存微信报告应一致;无需为了验证登录再次调用收费检测。
5. 如微信自身页面提示域名或 scope 权限错误,请核对对应 AppID 公众号的「网页授权域名」是否为 `1me.xajuzi.com`、是否有网页授权权限;这些设置不能由域名校验文件存在或基础接口令牌通过来推断。
服务端排查命令:
```bash
sudo journalctl -u juzi-h5.service --since '10 minutes ago' --no-pager | rg '\[auth/wechat\]'
```
只需反馈页面是否进入首页/报告列表,或错误页面截图。不要传授权 code、Cookie、OpenID、AppSecret 或接口令牌。
@@ -2,6 +2,8 @@
时间:2026-10-11(北京时间)。服务器:`ubuntu@1me.xajuzi.com`,页面:`https://1me.xajuzi.com/state/`。
2026-10-12 最新状态:白名单已生效,生产服务器成功获取微信基础接口令牌,AppID/AppSecret 校验通过;新增账号切换、会话失效防串号和回调诊断,详见[本轮联调记录](微信登录联调-2026-10-12.md)。下文 `40164` 是历史结果,真实微信客户端授权仍待验证。
## 后续更新:已配置真实凭据
用户提供凭据后,已将其写入 `/etc/juzi/wechat.env` 并重启服务。该文件仅 root 可读写(600),目录为 700;临时凭据文件已移除,未写入代码库或前端。