优化 token 处理逻辑,统一 createCookie 调用格式,返回 token 过期时间

This commit is contained in:
2026-02-02 17:02:20 +08:00
parent a0f0f65d20
commit 82e3392b36
5 changed files with 55 additions and 27 deletions

View File

@@ -70,9 +70,16 @@ interface Store<T> {
expire: (key: string, ttl?: number) => Promise<void>;
delObject: (value?: T) => Promise<void>;
keys: (key?: string) => Promise<string[]>;
setToken: (value: { accessToken: string; refreshToken: string; value?: T }, opts?: StoreSetOpts) => Promise<void>;
setToken: (value: { accessToken: string; refreshToken: string; value?: T }, opts?: StoreSetOpts) => Promise<TokenData>;
delKeys: (keys: string[]) => Promise<number>;
}
type TokenData = {
accessToken: string;
accessTokenExpiresAt: number;
refreshToken?: string;
refreshTokenExpiresAt?: number;
}
export class RedisTokenStore implements Store<OauthUser> {
redis: Redis;
private prefix: string = 'oauth:';
@@ -131,7 +138,7 @@ export class RedisTokenStore implements Store<OauthUser> {
await this.del(userPrefix + ':token:' + accessToken);
}
}
async setToken(data: { accessToken: string; refreshToken: string; value?: OauthUser }, opts?: StoreSetOpts) {
async setToken(data: { accessToken: string; refreshToken: string; value?: OauthUser }, opts?: StoreSetOpts): Promise<TokenData> {
const { accessToken, refreshToken, value } = data;
let userPrefix = 'user:' + value?.id;
if (value?.orgId) {
@@ -163,14 +170,20 @@ export class RedisTokenStore implements Store<OauthUser> {
await this.set(accessToken, JSON.stringify(value), expire);
await this.set(userPrefix + ':token:' + accessToken, accessToken, expire);
let refreshTokenExpiresAt = Math.min(expire * 7, 60 * 60 * 24 * 30, 60 * 60 * 24 * 365); // 最大为一年
if (refreshToken) {
let refreshTokenExpire = Math.min(expire * 7, 60 * 60 * 24 * 30, 60 * 60 * 24 * 365); // 最大为一年
// 小于7天, 则设置为7天
if (refreshTokenExpire < 60 * 60 * 24 * 7) {
refreshTokenExpire = 60 * 60 * 24 * 7;
if (refreshTokenExpiresAt < 60 * 60 * 24 * 7) {
refreshTokenExpiresAt = 60 * 60 * 24 * 7;
}
await this.set(refreshToken, JSON.stringify(value), refreshTokenExpire);
await this.set(userPrefix + ':refreshToken:' + refreshToken, refreshToken, refreshTokenExpire);
await this.set(refreshToken, JSON.stringify(value), refreshTokenExpiresAt);
await this.set(userPrefix + ':refreshToken:' + refreshToken, refreshToken, refreshTokenExpiresAt);
}
return {
accessToken,
accessTokenExpiresAt: expire,
refreshToken,
refreshTokenExpiresAt,
}
}
async delKeys(keys: string[]) {
@@ -206,10 +219,7 @@ export class OAuth<T extends OauthUser> {
async generateToken(
user: T,
expandOpts?: StoreSetOpts,
): Promise<{
accessToken: string;
refreshToken?: string;
}> {
): Promise<TokenData> {
// 拥有refreshToken 为 true 时accessToken 为 st_ 开头refreshToken 为 rk_开头
// 意思是secretToken 和 secretKey的缩写
const accessToken = expandOpts?.hasRefreshToken ? 'st_' + randomId32() : 'sk_' + randomId64();
@@ -227,9 +237,9 @@ export class OAuth<T extends OauthUser> {
user.oauthExpand.refreshToken = refreshToken;
}
}
await this.store.setToken({ accessToken, refreshToken, value: user }, expandOpts);
const tokenData = await this.store.setToken({ accessToken, refreshToken, value: user }, expandOpts);
return { accessToken, refreshToken };
return tokenData;
}
async saveSecretKey(oauthUser: T, secretKey: string, opts?: StoreSetOpts) {
// 生成一个secretKey