3.9 KiB
3.9 KiB
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实例。
-
问题根本原因:
- 系统原先将会话信息保持在
AkSupa.session/AkSupa.user(内存)中,页面刷新或应用重启会清空内存,导致supa.getSession()返回null。 - 虽然
AkReq.setToken将access_token/refresh_token持久化到unistorage,但AkSupa在启动时没有读取这些持久化 token 并执行恢复/刷新流程(或未将 refresh token 注入到AkSupa),因此无法重建会话。 - 若 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)。
- 在
-
如何验证(开发环境):
- 登录并确认本地存储中有 token(通过控制台或在 uni 环境运行):
uni.getStorageSync('akreq_access_token')uni.getStorageSync('akreq_refresh_token')
- 刷新页面或重启应用,打开控制台查找初始化日志或错误(
Supabase instance init failed等)。 - 在页面中(例如
pages/mall/delivery/index.uvue)查看已有的调试输出:searchsupa session=的 console 日志,应显示非 null session(若 refresh 成功)。 - 若恢复失败,请检查后端 refresh 接口是否返回 200,以及 refresh token 是否已过期。
- 登录并确认本地存储中有 token(通过控制台或在 uni 环境运行):
-
后续建议(可选):
- 在
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 流程并合理设置过期与刷新策略。
- 切勿在代码中硬编码匿名 key 或生产密钥;请在
如果你需要,我可以继续:
- 在
AkSupa中实现“登录后持久化 session JSON”的补丁,并在signOut时清理; - 或添加更详细的调试输出帮助定位某次具体恢复失败的 HTTP 请求和响应。
文件路径:components/supadb/SESSION_RECOVERY.md