优化登录逻辑的实现,将认证请求和token验证的处理分成两个逻辑文件。新增交叉评查任务列表的页面(尚未对接真实数据)。
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Token管理服务
|
||||
* 负责处理OAuth访问令牌的刷新和管理
|
||||
* 如果需要添加新的Token相关功能:
|
||||
* 1. 优先考虑在 `TokenManager` 中添加
|
||||
* 2. 如果需要新的网络请求,在 `OAuthClient` 中添加
|
||||
*/
|
||||
import { OAuthClient } from "./oauth-client";
|
||||
import { OAUTH_CONFIG } from "~/config/api-config";
|
||||
|
||||
interface TokenInfo {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
tokenIssuedAt: number;
|
||||
tokenExpiresIn: number;
|
||||
}
|
||||
|
||||
interface RefreshResult {
|
||||
success: boolean;
|
||||
newTokenInfo?: TokenInfo;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token管理服务
|
||||
* 负责处理OAuth访问令牌的刷新和管理
|
||||
*/
|
||||
export class TokenManager {
|
||||
private oauthClient: OAuthClient;
|
||||
|
||||
constructor() {
|
||||
this.oauthClient = new OAuthClient(OAUTH_CONFIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查token是否过期
|
||||
*/
|
||||
isTokenExpired(tokenInfo: TokenInfo): boolean {
|
||||
const now = Date.now();
|
||||
const expiresAt = tokenInfo.tokenIssuedAt + (tokenInfo.tokenExpiresIn * 1000);
|
||||
return now >= expiresAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查token是否需要刷新(提前5分钟)
|
||||
*/
|
||||
shouldRefreshToken(tokenInfo: TokenInfo, refreshThresholdMinutes: number = 5): boolean {
|
||||
const now = Date.now();
|
||||
const expiresAt = tokenInfo.tokenIssuedAt + (tokenInfo.tokenExpiresIn * 1000);
|
||||
const refreshThreshold = refreshThresholdMinutes * 60 * 1000;
|
||||
return now >= (expiresAt - refreshThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token剩余有效时间(秒)
|
||||
*/
|
||||
getTokenRemainingTime(tokenInfo: TokenInfo): number {
|
||||
const now = Date.now();
|
||||
const expiresAt = tokenInfo.tokenIssuedAt + (tokenInfo.tokenExpiresIn * 1000);
|
||||
return Math.floor((expiresAt - now) / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*/
|
||||
async refreshToken(refreshToken: string): Promise<RefreshResult> {
|
||||
try {
|
||||
console.log("开始刷新访问令牌...");
|
||||
|
||||
const newTokenResponse = await this.oauthClient.refreshAccessToken(refreshToken);
|
||||
|
||||
if (!newTokenResponse) {
|
||||
console.error("刷新令牌失败:服务器返回空响应");
|
||||
return {
|
||||
success: false,
|
||||
error: "服务器返回空响应"
|
||||
};
|
||||
}
|
||||
|
||||
const newTokenInfo: TokenInfo = {
|
||||
accessToken: newTokenResponse.access_token,
|
||||
refreshToken: newTokenResponse.refresh_token,
|
||||
tokenIssuedAt: Date.now(),
|
||||
tokenExpiresIn: newTokenResponse.expires_in
|
||||
};
|
||||
|
||||
console.log(`令牌刷新成功,新令牌有效期: ${newTokenResponse.expires_in}秒`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
newTokenInfo
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error("刷新令牌时发生错误:", error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : "未知错误"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并自动刷新token(如果需要)
|
||||
*/
|
||||
async checkAndRefreshToken(tokenInfo: TokenInfo): Promise<RefreshResult> {
|
||||
// 如果token已过期,必须刷新
|
||||
if (this.isTokenExpired(tokenInfo)) {
|
||||
console.log("Token已过期,尝试刷新...");
|
||||
return this.refreshToken(tokenInfo.refreshToken);
|
||||
}
|
||||
|
||||
// 如果token即将过期,主动刷新
|
||||
if (this.shouldRefreshToken(tokenInfo)) {
|
||||
const remainingTime = this.getTokenRemainingTime(tokenInfo);
|
||||
console.log(`Token将在${remainingTime}秒后过期,主动刷新...`);
|
||||
return this.refreshToken(tokenInfo.refreshToken);
|
||||
}
|
||||
|
||||
// Token仍然有效,无需刷新
|
||||
return {
|
||||
success: true,
|
||||
newTokenInfo: tokenInfo
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化token到期时间
|
||||
*/
|
||||
formatTokenExpiry(tokenInfo: TokenInfo): string {
|
||||
const expiresAt = new Date(tokenInfo.tokenIssuedAt + (tokenInfo.tokenExpiresIn * 1000));
|
||||
return expiresAt.toLocaleString('zh-CN');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token状态信息(用于调试)
|
||||
*/
|
||||
getTokenStatus(tokenInfo: TokenInfo): {
|
||||
isExpired: boolean;
|
||||
shouldRefresh: boolean;
|
||||
remainingTime: number;
|
||||
expiryTime: string;
|
||||
} {
|
||||
return {
|
||||
isExpired: this.isTokenExpired(tokenInfo),
|
||||
shouldRefresh: this.shouldRefreshToken(tokenInfo),
|
||||
remainingTime: this.getTokenRemainingTime(tokenInfo),
|
||||
expiryTime: this.formatTokenExpiry(tokenInfo)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例
|
||||
export const tokenManager = new TokenManager();
|
||||
Reference in New Issue
Block a user