Files
medical-mall/components/supadb/SESSION_RECOVERY.md
2026-02-02 18:20:22 +08:00

42 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**Supabase 会话恢复说明supa session recovery**
- **目的**: 说明为什么刷新后 `session` / `user` 变为 `null`,以及我在项目中做了哪些修改来改善会话恢复。
- **文件变更**:
- **`components/supadb/aksupainstance.uts`**: 统一 Supabase 实例导出,新增 `supaReady` 初始化流程。在初始化时尝试从持久化 token`AkReq` 存储)读取 `access_token` / `refresh_token`,将 refresh token 注入到 `supa.session` 并调用 `supa.refreshSession()` 以恢复会话;保留 `ensureSupabaseReady()` 作为兼容接口。
- **`utils/store.uts`**: 将 `import` 改为 `import supa, { supaReady }`,并在获取 session 前 `await supaReady`,确保恢复逻辑已经运行完毕。
- **`utils/sapi.uts`**、**`pages/sense/senseDataService.uts`** 及若干页面文件: 替换对旧 `ensureSupabaseReady` 的调用,改为 `await supaReady`,并使用默认导出的 `supa` 实例。
- **问题根本原因**:
1. 系统原先将会话信息保持在 `AkSupa.session` / `AkSupa.user`(内存)中,页面刷新或应用重启会清空内存,导致 `supa.getSession()` 返回 `null`
2. 虽然 `AkReq.setToken``access_token` / `refresh_token` 持久化到 `uni` storage`AkSupa` 在启动时没有读取这些持久化 token 并执行恢复/刷新流程(或未将 refresh token 注入到 `AkSupa`),因此无法重建会话。
3. 若 refresh token 过期或没有被正确持久化,也会导致恢复失败。
- **我做的修改说明(要点)**:
-`aksupainstance.uts` 添加 `supaReady`:这是一个 Promise模块初始化时会尝试读取 `AkReq.getRefreshToken()` / `AkReq.getToken()`;若找到 refresh token则把其临时赋到 `supa.session`,再调用 `supa.refreshSession()` 以更新内存中的 session 和 user。
- 在所有依赖会话的模块中,在执行数据库请求前 `await supaReady`,确保恢复尝试已完成,避免 race condition页面刷新后立即调用 supa API 导致 401/空 session
- 保留向后兼容接口 `ensureSupabaseReady()`(内部直接返回 `supaReady`)。
- **如何验证(开发环境)**:
1. 登录并确认本地存储中有 token通过控制台或在 uni 环境运行):
- `uni.getStorageSync('akreq_access_token')`
- `uni.getStorageSync('akreq_refresh_token')`
2. 刷新页面或重启应用,打开控制台查找初始化日志或错误(`Supabase instance init failed` 等)。
3. 在页面中(例如 `pages/mall/delivery/index.uvue`查看已有的调试输出search `supa session=` 的 console 日志,应显示非 null session若 refresh 成功)。
4. 若恢复失败,请检查后端 refresh 接口是否返回 200以及 refresh token 是否已过期。
- **后续建议(可选)**:
-`AkSupa.signIn` / `refreshSession` 成功时,将完整 session或至少 `refresh_token`)写入 `uni.setStorageSync`(持久化),并在 `signOut` 时清除,这样可以进一步减少恢复失败的情况。
-`supa.session` 的 JSON 快照也写入 storage作为额外冗余并在 init 时尝试直接恢复(注意安全和敏感信息保护)。
- 增加更详细的日志(成功/失败原因),并在 UI 层对“登录过期”做更友好的提示或自动跳转到登录页。
- **注意事项**:
- 切勿在代码中硬编码匿名 key 或生产密钥;请在 `ak/config.uts` 中正确配置 `SUPA_URL``SUPA_KEY`
- refresh token 本身也是敏感凭证,应妥善保管;如需长期保持登录,建议使用 refresh 流程并合理设置过期与刷新策略。
如果你需要,我可以继续:
-`AkSupa` 中实现“登录后持久化 session JSON”的补丁并在 `signOut` 时清理;
- 或添加更详细的调试输出帮助定位某次具体恢复失败的 HTTP 请求和响应。
文件路径components/supadb/SESSION_RECOVERY.md