fix(miniprogram): 退出登录后刷新仍保持登录态
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

根因:logout 清除 storage 期间并发请求触发 tryRefreshToken 写回新 token
修复:添加 isLoggingOut 标记,logout 时先标记阻止 token 刷新竞态
This commit is contained in:
iven
2026-05-10 10:36:17 +08:00
parent 11101ac204
commit 3c828bfc4a
2 changed files with 14 additions and 1 deletions

View File

@@ -30,8 +30,18 @@ async function getHeaders(): Promise<Record<string, string>> {
// --- Token refresh deduplication --- // --- Token refresh deduplication ---
let refreshPromise: Promise<boolean> | null = null; let refreshPromise: Promise<boolean> | null = null;
let isLoggingOut = false;
export function markLoggingOut(): void {
isLoggingOut = true;
}
export function clearLoggingOut(): void {
isLoggingOut = false;
}
async function tryRefreshToken(): Promise<boolean> { async function tryRefreshToken(): Promise<boolean> {
if (isLoggingOut) return false;
if (refreshPromise) return refreshPromise; if (refreshPromise) return refreshPromise;
refreshPromise = doRefresh(); refreshPromise = doRefresh();
refreshPromise.finally(() => { refreshPromise = null; }); refreshPromise.finally(() => { refreshPromise = null; });

View File

@@ -2,7 +2,7 @@ import { create } from 'zustand';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import * as authApi from '@/services/auth'; import * as authApi from '@/services/auth';
import { secureGet, secureSet, secureRemove } from '@/utils/secure-storage'; import { secureGet, secureSet, secureRemove } from '@/utils/secure-storage';
import { clearRequestCache } from '@/services/request'; import { clearRequestCache, markLoggingOut, clearLoggingOut } from '@/services/request';
interface BindPhoneResp { interface BindPhoneResp {
access_token: string; access_token: string;
@@ -96,6 +96,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
secureSet('user_roles', JSON.stringify(roles)); secureSet('user_roles', JSON.stringify(roles));
secureSet('tenant_id', user.tenant_id || ''); secureSet('tenant_id', user.tenant_id || '');
set({ user, roles, loading: false }); set({ user, roles, loading: false });
clearLoggingOut();
return true; return true;
} }
secureSet('wechat_openid', resp.openid); secureSet('wechat_openid', resp.openid);
@@ -128,6 +129,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
secureSet('tenant_id', tokenData.user?.tenant_id || ''); secureSet('tenant_id', tokenData.user?.tenant_id || '');
secureRemove('wechat_openid'); secureRemove('wechat_openid');
set({ user: tokenData.user, roles, loading: false }); set({ user: tokenData.user, roles, loading: false });
clearLoggingOut();
return true; return true;
} catch (err: any) { } catch (err: any) {
secureRemove('wechat_openid'); secureRemove('wechat_openid');
@@ -155,6 +157,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
}, },
logout: () => { logout: () => {
markLoggingOut();
clearRequestCache(); clearRequestCache();
secureRemove('access_token'); secureRemove('access_token');
secureRemove('refresh_token'); secureRemove('refresh_token');