aptx-token-store
npx skills add https://github.com/haibaraaiaptx/aptx-skill --skill aptx-token-store
Agent 安装分布
Skill 文档
aptx-token-store
æ ¸å¿è§è
å¨å®ç° token å卿½è±¡æ¶ï¼æä»¥ä¸è§èæ§è¡ï¼
- å®ç°
TokenStoreçæå°è½åï¼getTokenãsetTokenãclearTokenã - è¥éè¦è¿ææ§å¶ï¼æä¾
getMeta/setMetaægetRecord/setRecordï¼å¹¶ç¡®ä¿meta.expiresAtå¯è¯»åã - ä¿æå®ç°æ ä¸å¡è¦åï¼ä¸å
å«è¯·æ±é»è¾ï¼ä¸ä¾èµ
@aptx/api-coreã - æç¯å¢ç¸å ³è½åæ¾å°ç¬ç«å ä¸ï¼å¦ cookieãå°ç¨åºãå åï¼ã
- 以
@aptx/api-plugin-authä½ä¸ºä¸»è¦æ¶è´¹æ¹è¿è¡èè°æµè¯ã - æææ¹æ³å¿ é¡»ä¿æåæ¥/弿¥ä¸è´æ§ï¼ä¸å¯æ··ç¨ã
æ¥å£å®ä¹
import type { TokenStore, TokenMeta, TokenRecord, TokenStoreResolver } from '@aptx/token-store';
interface TokenStore {
// æ ¸å¿æ¹æ³ï¼å¿
é¡»å®ç°ï¼
getToken(): string | undefined | Promise<string | undefined>;
setToken(token: string, meta?: TokenMeta): void | Promise<void>;
clearToken(): void | Promise<void>;
// å¯éæ¹æ³ï¼æ¯æè¿ææ§å¶ï¼
getMeta?(): TokenMeta | undefined | Promise<TokenMeta | undefined>;
setMeta?(meta: TokenMeta): void | Promise<void>;
getRecord?(): TokenRecord | undefined | Promise<TokenRecord | undefined>;
setRecord?(record: TokenRecord): void | Promise<void>;
}
interface TokenMeta {
expiresAt?: number; // æ¶é´æ³ï¼æ¯«ç§ï¼
[key: string]: unknown;
}
interface TokenRecord {
token?: string;
meta?: TokenMeta;
}
// Store è§£æå¨ç±»åï¼ç¨äº @aptx/api-plugin-authï¼
type TokenStoreResolver =
| TokenStore // ç´æ¥å®ä¾ï¼ååå
¼å®¹ï¼
| (() => TokenStore) // 忥工å彿°
| (() => Promise<TokenStore>); // 弿¥å·¥å彿°ï¼SSRï¼
å·¥å ·å½æ°
resolveTokenStore
ç»ä¸å¤çä¸ç§ TokenStoreResolver å½¢å¼ï¼è¿å TokenStore å®ä¾ï¼
import { resolveTokenStore } from '@aptx/token-store';
// ä¸ç§å½¢å¼é½ä¼è¢«æ£ç¡®è§£æä¸º TokenStore
const store1 = await resolveTokenStore(directInstance);
const store2 = await resolveTokenStore(syncFactory);
const store3 = await resolveTokenStore(asyncFactory);
使ç¨åºæ¯ï¼ å½ä½ éè¦ç»ä¸å¤çç¨æ·ä¼ å
¥ç store åæ°æ¶ä½¿ç¨ã@aptx/api-plugin-auth å
é¨ä½¿ç¨æ¤å½æ°ã
å®ç°æ£æ¥æ¸ å
- å®ç°äº
getToken()ãsetToken()ãclearToken()ä¸ä¸ªæ ¸å¿æ¹æ³ - å¦éè¿ææ§å¶ï¼å®ç°äº
getMeta()/setMeta()ï¼ægetRecord()/setRecord()ï¼ -
meta.expiresAtæ¯ææ¶é´æ³æ ¼å¼ï¼æ¯«ç§ï¼ - æææ¹æ³ä¿æåæ¥/弿¥ä¸è´æ§ï¼ä¸å¯æ··ç¨ï¼
-
clearToken()åæ¶æ¸ é¤ token å meta æ°æ® - ä¸ä¾èµ
@aptx/api-coreæè¯·æ±åº - å®ç°äº
TokenStoreFactory.create()ï¼å¦æéè¦é ç½®ï¼
忥/弿¥éæ©è§å
| åºæ¯ | æ¨è | çç± |
|---|---|---|
| localStorage/sessionStorage | 忥 | é»å¡æ¶é´æç |
| cookie (js-cookie) | 忥 | å åæä½ |
| IndexedDB | 弿¥ | I/O æä½ |
| ç½ç»è¯·æ± | 弿¥ | å¿ é¡»å¼æ¥ |
| å ååå¨ | 忥 | æ I/O |
| å°ç¨åºåå¨ (wx.getStorageSync) | 忥 | 忥 API æ´å¯é |
éè¦ååï¼ æææ¹æ³å¿ é¡»ä¿æåæ¥/弿¥ä¸è´æ§ï¼ä¸å¯æ··ç¨ã
å®ç°æå
详ç»å®ç°ç¤ºä¾
宿´çå®ç°ç¤ºä¾è¯·åèï¼
- æå°å®ç°ï¼æ è¿ææ§å¶ï¼
- 宿´å®ç°ï¼å¸¦è¿æç®¡çï¼
- Cookie å®ç°
- LocalStorage å®ç°
- å°ç¨åºå®ç°
- å åå®ç°ï¼ä» ç¨äºæµè¯ï¼
- TokenStoreFactory 模å¼
TokenStoreFactory 模å¼
å½å®ç°éè¦é ç½®æ¶ï¼ä½¿ç¨ Factory 模å¼ï¼
import type { TokenStoreFactory } from '@aptx/token-store';
// å®ä¹é
ç½®æ¥å£
export interface YourStoreOptions {
tokenKey?: string;
metaKey?: string;
prefix?: string;
}
// å®ç°ç±»
class YourTokenStore implements TokenStore {
constructor(private options: YourStoreOptions) {
this.tokenKey = options.tokenKey ?? 'aptx_token';
this.metaKey = options.metaKey ?? 'aptx_token_meta';
this.prefix = options.prefix ?? '';
}
private readonly tokenKey: string;
private readonly metaKey: string;
private readonly prefix: string;
// ... å®ç° TokenStore æ¹æ³
}
// Factory 彿°
export const createYourTokenStore: TokenStoreFactory<YourStoreOptions>["create"] = (
options: YourStoreOptions = {}
) => {
return new YourTokenStore(options);
};
ä¸ @aptx/api-plugin-auth éæ
åºæ¬éææ¨¡å¼
import { createAuthMiddleware } from '@aptx/api-plugin-auth';
client.use(createAuthMiddleware({
store, // ä½ ç TokenStore å®ç°
refreshLeewayMs: 60_000, // æå60ç§å·æ°
refreshToken: async () => {
// è¿åæ ¼å¼1ï¼å®æ´å¯¹è±¡ï¼æ¨èï¼
return {
token: 'new-token',
expiresAt: Date.now() + 30 * 60 * 1000 // 30åéåè¿æ
};
// æè¿åæ ¼å¼2ï¼ä»
tokenï¼ä¸èªå¨è®¾ç½® expiresAtï¼
// return 'new-token';
},
}));
å·¥å彿°æ¨¡å¼ï¼æ¨èï¼
store åæ°æ¯æä¸ç§å½¢å¼ï¼ä¾¿äºæµè§å¨ç«¯å SSR ç«¯ä¿æ API ä¸è´æ§ï¼
// å½¢å¼ 1ï¼ç´æ¥å®ä¾ï¼ååå
¼å®¹ï¼
const store = new CookieTokenStore();
createAuthMiddleware({ store, ... });
// å½¢å¼ 2ï¼åæ¥å·¥å彿°ï¼æµè§å¨ç«¯æ¨èï¼
createAuthMiddleware({
store: () => store,
...
});
// å½¢å¼ 3ï¼å¼æ¥å·¥å彿°ï¼SSR 端å¿
é¡»ï¼
createAuthMiddleware({
store: async () => {
const cookies = await getNextCookies();
return new SsrCookieTokenStore({
getCookieHeader: () => cookies.toString(),
setCookie: (v) => { ... },
});
},
...
});
éæè¦æ±
- å¿
é¡»å®ç°ï¼
getToken()– 读å token ç¨äºè¯·æ± - å¿
é¡»å®ç°ï¼
setToken()– ä¿åå·æ°åç token - å¿
é¡»å®ç°ï¼
clearToken()– å·æ°å¤±è´¥æ¶æ¸ 餿 æ token - æ¨èå®ç°ï¼
getMeta()– æ¯æexpiresAt读åï¼ä¸»å¨å·æ°ï¼ - æ¨èå®ç°ï¼
setMeta()– æ¯æexpiresAtåå ¥
æ´å¤éæè¯¦æ
宿´çéææåå示ä¾è¯·åè references/integration.mdï¼å æ¬ï¼
- api-plugin-auth çå ³é®è°ç¨é»è¾
- 常è§éæåºæ¯ï¼localStorageãCookieãå°ç¨åºãæµè¯ï¼
- 忥/弿¥éææ³¨æäºé¡¹
- è°è¯æå·§
æµè¯
æµè¯æ¨¡å¼
æµè¯ç¸å ³çå 容请åè references/test-patterns.mdï¼å æ¬ï¼
- Mock å卿¨¡å¼
- 使ç¨å ååå¨è¿è¡æµè¯
- 宿´çæµè¯ç¨ä¾ç¤ºä¾
å®ç°æ³¨æäºé¡¹
å®ç°è¿ç¨ä¸ç注æäºé¡¹è¯·åè references/test-patterns.md#å®ç°æ³¨æäºé¡¹ï¼å æ¬ï¼
- é误å¤çï¼localStorage è¶ éãcookie ç¦ç¨çï¼
- ç±»åå®å ¨ï¼ä½¿ç¨å®æ´ç±»åå®ä¹ï¼
- æ§è½èèï¼é¿å é»å¡ãå¹¶åæ§å¶ï¼
- å®å ¨æ§ï¼Cookie é ç½®ãææä¿¡æ¯å å¯ãXSS 鲿¤ï¼