轻松聘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

84 lines
2.5 KiB

import { storageGet, storageSet, storageRemove } from './storage';
/* ===================== 双 Token 存储(access + refresh) =====================
* 规范 §4:Access Token 用于业务请求;Refresh Token 只提交给 /auth/refresh。
*
* 鉴权请求头在 fetch 构造时是「同步」的,但 AsyncStorage 是异步的,
* 因此这里保留一份内存单例,供请求层同步读取 accessToken;
* 持久化仍走 storage(qingsongpin: 前缀),由 hydrateTokens 在启动时回填。
*/
const KEY_ACCESS = 'auth:accessToken';
const KEY_REFRESH = 'auth:refreshToken';
const KEY_EXP = 'auth:expiresAt';
export interface TokenPair {
accessToken: string;
refreshToken: string;
/** accessToken 过期时间戳(毫秒);后端可能不返回,故可选 */
expiresAt?: number;
}
let memory: TokenPair | null = null;
/** 应用启动时调用一次:从持久化回填内存态;失败静默降级为未登录 */
export async function hydrateTokens(): Promise<void> {
try {
const [access, refresh, exp] = await Promise.all([
storageGet(KEY_ACCESS),
storageGet(KEY_REFRESH),
storageGet(KEY_EXP),
]);
if (access && refresh) {
memory = {
accessToken: access,
refreshToken: refresh,
expiresAt: exp ? Number(exp) : undefined,
};
}
} catch {
/* 降级为未登录 */
}
}
/** 同步读取 accessToken(供请求层构造 Authorization 头) */
export function getAccessToken(): string | null {
return memory?.accessToken ?? null;
}
/** 同步读取完整 Token 对(供刷新判断是否有 refreshToken) */
export function getTokens(): TokenPair | null {
return memory;
}
/** 写入并持久化;expiresAt 缺省时不覆盖已存值 */
export async function setTokens(
accessToken: string,
refreshToken: string,
expiresAt?: number,
): Promise<void> {
memory = { accessToken, refreshToken, expiresAt };
const writes: Promise<void>[] = [
storageSet(KEY_ACCESS, accessToken),
storageSet(KEY_REFRESH, refreshToken),
];
if (expiresAt !== undefined) {
writes.push(storageSet(KEY_EXP, String(expiresAt)));
}
await Promise.all(writes);
}
/** 清空(登出 / 刷新失败 / 401 清会话):内存与持久化一并清 */
export async function clearTokens(): Promise<void> {
memory = null;
await Promise.all([
storageRemove(KEY_ACCESS),
storageRemove(KEY_REFRESH),
storageRemove(KEY_EXP),
]);
}
/** 仅供测试:复位内存态,避免用例间污染 */
export function __resetTokenMemory(): void {
memory = null;
}