优化 token 处理逻辑,统一 createCookie 调用格式,返回 token 过期时间
This commit is contained in:
@@ -62,7 +62,13 @@ export class User extends Model {
|
|||||||
oauthUser.orgId = id;
|
oauthUser.orgId = id;
|
||||||
}
|
}
|
||||||
const token = await oauth.generateToken(oauthUser, { type: loginType, hasRefreshToken: true, ...expand });
|
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
|
* 验证token
|
||||||
|
|||||||
@@ -70,9 +70,16 @@ interface Store<T> {
|
|||||||
expire: (key: string, ttl?: number) => Promise<void>;
|
expire: (key: string, ttl?: number) => Promise<void>;
|
||||||
delObject: (value?: T) => Promise<void>;
|
delObject: (value?: T) => Promise<void>;
|
||||||
keys: (key?: string) => Promise<string[]>;
|
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>;
|
delKeys: (keys: string[]) => Promise<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TokenData = {
|
||||||
|
accessToken: string;
|
||||||
|
accessTokenExpiresAt: number;
|
||||||
|
refreshToken?: string;
|
||||||
|
refreshTokenExpiresAt?: number;
|
||||||
|
}
|
||||||
export class RedisTokenStore implements Store<OauthUser> {
|
export class RedisTokenStore implements Store<OauthUser> {
|
||||||
redis: Redis;
|
redis: Redis;
|
||||||
private prefix: string = 'oauth:';
|
private prefix: string = 'oauth:';
|
||||||
@@ -131,7 +138,7 @@ export class RedisTokenStore implements Store<OauthUser> {
|
|||||||
await this.del(userPrefix + ':token:' + accessToken);
|
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;
|
const { accessToken, refreshToken, value } = data;
|
||||||
let userPrefix = 'user:' + value?.id;
|
let userPrefix = 'user:' + value?.id;
|
||||||
if (value?.orgId) {
|
if (value?.orgId) {
|
||||||
@@ -163,14 +170,20 @@ export class RedisTokenStore implements Store<OauthUser> {
|
|||||||
|
|
||||||
await this.set(accessToken, JSON.stringify(value), expire);
|
await this.set(accessToken, JSON.stringify(value), expire);
|
||||||
await this.set(userPrefix + ':token:' + accessToken, accessToken, 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) {
|
if (refreshToken) {
|
||||||
let refreshTokenExpire = Math.min(expire * 7, 60 * 60 * 24 * 30, 60 * 60 * 24 * 365); // 最大为一年
|
|
||||||
// 小于7天, 则设置为7天
|
// 小于7天, 则设置为7天
|
||||||
if (refreshTokenExpire < 60 * 60 * 24 * 7) {
|
if (refreshTokenExpiresAt < 60 * 60 * 24 * 7) {
|
||||||
refreshTokenExpire = 60 * 60 * 24 * 7;
|
refreshTokenExpiresAt = 60 * 60 * 24 * 7;
|
||||||
}
|
}
|
||||||
await this.set(refreshToken, JSON.stringify(value), refreshTokenExpire);
|
await this.set(refreshToken, JSON.stringify(value), refreshTokenExpiresAt);
|
||||||
await this.set(userPrefix + ':refreshToken:' + refreshToken, refreshToken, refreshTokenExpire);
|
await this.set(userPrefix + ':refreshToken:' + refreshToken, refreshToken, refreshTokenExpiresAt);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
accessToken,
|
||||||
|
accessTokenExpiresAt: expire,
|
||||||
|
refreshToken,
|
||||||
|
refreshTokenExpiresAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async delKeys(keys: string[]) {
|
async delKeys(keys: string[]) {
|
||||||
@@ -206,10 +219,7 @@ export class OAuth<T extends OauthUser> {
|
|||||||
async generateToken(
|
async generateToken(
|
||||||
user: T,
|
user: T,
|
||||||
expandOpts?: StoreSetOpts,
|
expandOpts?: StoreSetOpts,
|
||||||
): Promise<{
|
): Promise<TokenData> {
|
||||||
accessToken: string;
|
|
||||||
refreshToken?: string;
|
|
||||||
}> {
|
|
||||||
// 拥有refreshToken 为 true 时,accessToken 为 st_ 开头,refreshToken 为 rk_开头
|
// 拥有refreshToken 为 true 时,accessToken 为 st_ 开头,refreshToken 为 rk_开头
|
||||||
// 意思是secretToken 和 secretKey的缩写
|
// 意思是secretToken 和 secretKey的缩写
|
||||||
const accessToken = expandOpts?.hasRefreshToken ? 'st_' + randomId32() : 'sk_' + randomId64();
|
const accessToken = expandOpts?.hasRefreshToken ? 'st_' + randomId32() : 'sk_' + randomId64();
|
||||||
@@ -227,9 +237,9 @@ export class OAuth<T extends OauthUser> {
|
|||||||
user.oauthExpand.refreshToken = refreshToken;
|
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) {
|
async saveSecretKey(oauthUser: T, secretKey: string, opts?: StoreSetOpts) {
|
||||||
// 生成一个secretKey
|
// 生成一个secretKey
|
||||||
|
|||||||
@@ -59,10 +59,7 @@ app
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await config.update({
|
await config.update({
|
||||||
data: {
|
data: data,
|
||||||
...config.data,
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
...rest,
|
...rest,
|
||||||
});
|
});
|
||||||
if (config.data?.permission?.share === 'public') {
|
if (config.data?.permission?.share === 'public') {
|
||||||
@@ -80,7 +77,7 @@ app
|
|||||||
});
|
});
|
||||||
if (config) {
|
if (config) {
|
||||||
await config.update({
|
await config.update({
|
||||||
data: { ...config.data, ...data },
|
data: data,
|
||||||
...rest,
|
...rest,
|
||||||
});
|
});
|
||||||
ctx.body = config;
|
ctx.body = config;
|
||||||
|
|||||||
@@ -153,7 +153,9 @@ app
|
|||||||
browser: someInfo['user-agent'],
|
browser: someInfo['user-agent'],
|
||||||
host: someInfo.host,
|
host: someInfo.host,
|
||||||
});
|
});
|
||||||
createCookie(token, ctx);
|
createCookie({
|
||||||
|
token: token.accessToken
|
||||||
|
}, ctx);
|
||||||
ctx.body = token;
|
ctx.body = token;
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
@@ -259,7 +261,10 @@ app
|
|||||||
const refreshToken = accessUser.oauthExpand?.refreshToken;
|
const refreshToken = accessUser.oauthExpand?.refreshToken;
|
||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
const result = await User.oauth.refreshToken(refreshToken);
|
const result = await User.oauth.refreshToken(refreshToken);
|
||||||
createCookie(result, ctx);
|
createCookie({
|
||||||
|
token: result.accessToken
|
||||||
|
}, ctx);
|
||||||
|
|
||||||
ctx.body = result;
|
ctx.body = result;
|
||||||
return;
|
return;
|
||||||
} else if (accessUser) {
|
} else if (accessUser) {
|
||||||
@@ -268,7 +273,9 @@ app
|
|||||||
...accessUser.oauthExpand,
|
...accessUser.oauthExpand,
|
||||||
hasRefreshToken: true,
|
hasRefreshToken: true,
|
||||||
});
|
});
|
||||||
createCookie(result, ctx);
|
createCookie({
|
||||||
|
token: result.accessToken
|
||||||
|
}, ctx);
|
||||||
ctx.body = result;
|
ctx.body = result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -323,13 +330,17 @@ app
|
|||||||
if (orgsList.includes(username)) {
|
if (orgsList.includes(username)) {
|
||||||
if (tokenUsername === username) {
|
if (tokenUsername === username) {
|
||||||
const result = await User.oauth.resetToken(token);
|
const result = await User.oauth.resetToken(token);
|
||||||
createCookie(result, ctx);
|
createCookie({
|
||||||
|
token: result.accessToken,
|
||||||
|
}, ctx);
|
||||||
await User.oauth.delToken(token);
|
await User.oauth.delToken(token);
|
||||||
ctx.body = result;
|
ctx.body = result;
|
||||||
} else {
|
} else {
|
||||||
const user = await User.findOne({ where: { username } });
|
const user = await User.findOne({ where: { username } });
|
||||||
const result = await user.createToken(userId, 'default');
|
const result = await user.createToken(userId, 'default');
|
||||||
createCookie(result, ctx);
|
createCookie({
|
||||||
|
token: result.accessToken,
|
||||||
|
}, ctx);
|
||||||
ctx.body = result;
|
ctx.body = result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -352,7 +363,9 @@ app
|
|||||||
const result = await User.oauth.refreshToken(refreshToken);
|
const result = await User.oauth.refreshToken(refreshToken);
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log('refreshToken result', result);
|
console.log('refreshToken result', result);
|
||||||
createCookie(result, ctx);
|
createCookie({
|
||||||
|
token: result.accessToken,
|
||||||
|
}, ctx);
|
||||||
ctx.body = result;
|
ctx.body = result;
|
||||||
} else {
|
} else {
|
||||||
ctx.throw(500, 'Refresh Token Failed, please login again');
|
ctx.throw(500, 'Refresh Token Failed, please login again');
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ app
|
|||||||
const token = JSON.parse(data);
|
const token = JSON.parse(data);
|
||||||
if (token.accessToken) {
|
if (token.accessToken) {
|
||||||
ctx.body = token;
|
ctx.body = token;
|
||||||
createCookie(token, ctx);
|
createCookie({
|
||||||
|
token: token.accessToken,
|
||||||
|
}, ctx);
|
||||||
} else {
|
} else {
|
||||||
ctx.throw(500, 'Checked error Failed, login failed, please login again');
|
ctx.throw(500, 'Checked error Failed, login failed, please login again');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user