42 lines
3.9 KiB
Markdown
42 lines
3.9 KiB
Markdown
**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
|