优化 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

@@ -62,7 +62,13 @@ export class User extends Model {
oauthUser.orgId = id;
}
const token = await oauth.generateToken(oauthUser, { type: loginType, hasRefreshToken: true, ...expand });
return { accessToken: token.accessToken, refreshToken: token.refreshToken, token: token.accessToken };
return {
accessToken: token.accessToken,
refreshToken: token.refreshToken,
token: token.accessToken,
accessTokenExpiresAt: token.accessTokenExpiresAt,
refreshTokenExpiresAt: token.refreshTokenExpiresAt,
};
}
/**
* 验证token

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

View File

@@ -59,10 +59,7 @@ app
}
}
await config.update({
data: {
...config.data,
...data,
},
data: data,
...rest,
});
if (config.data?.permission?.share === 'public') {
@@ -80,7 +77,7 @@ app
});
if (config) {
await config.update({
data: { ...config.data, ...data },
data: data,
...rest,
});
ctx.body = config;
@@ -177,7 +174,7 @@ app
const search: any = id ? { id } : { key };
const config = await ConfigModel.findOne({
where: {
...search
...search
},
});
if (config && config.uid === tuid) {

View File

@@ -153,7 +153,9 @@ app
browser: someInfo['user-agent'],
host: someInfo.host,
});
createCookie(token, ctx);
createCookie({
token: token.accessToken
}, ctx);
ctx.body = token;
})
.addTo(app);
@@ -259,7 +261,10 @@ app
const refreshToken = accessUser.oauthExpand?.refreshToken;
if (refreshToken) {
const result = await User.oauth.refreshToken(refreshToken);
createCookie(result, ctx);
createCookie({
token: result.accessToken
}, ctx);
ctx.body = result;
return;
} else if (accessUser) {
@@ -268,7 +273,9 @@ app
...accessUser.oauthExpand,
hasRefreshToken: true,
});
createCookie(result, ctx);
createCookie({
token: result.accessToken
}, ctx);
ctx.body = result;
return;
}
@@ -323,13 +330,17 @@ app
if (orgsList.includes(username)) {
if (tokenUsername === username) {
const result = await User.oauth.resetToken(token);
createCookie(result, ctx);
createCookie({
token: result.accessToken,
}, ctx);
await User.oauth.delToken(token);
ctx.body = result;
} else {
const user = await User.findOne({ where: { username } });
const result = await user.createToken(userId, 'default');
createCookie(result, ctx);
createCookie({
token: result.accessToken,
}, ctx);
ctx.body = result;
}
} else {
@@ -352,7 +363,9 @@ app
const result = await User.oauth.refreshToken(refreshToken);
if (result) {
console.log('refreshToken result', result);
createCookie(result, ctx);
createCookie({
token: result.accessToken,
}, ctx);
ctx.body = result;
} else {
ctx.throw(500, 'Refresh Token Failed, please login again');

View File

@@ -109,7 +109,9 @@ app
const token = JSON.parse(data);
if (token.accessToken) {
ctx.body = token;
createCookie(token, ctx);
createCookie({
token: token.accessToken,
}, ctx);
} else {
ctx.throw(500, 'Checked error Failed, login failed, please login again');
}