262 lines
7.4 KiB
JavaScript
262 lines
7.4 KiB
JavaScript
|
|
/**
|
|||
|
|
* Token管理工具类
|
|||
|
|
*/
|
|||
|
|
class TokenManager {
|
|||
|
|
|
|||
|
|
static TOKEN_KEY = 'yundage_token';
|
|||
|
|
static USER_KEY = 'yundage_user';
|
|||
|
|
static REFRESH_TOKEN_KEY = 'yundage_refresh_token';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 保存Token到本地存储
|
|||
|
|
* @param {string} token - JWT Token
|
|||
|
|
* @param {boolean} remember - 是否记住登录状态
|
|||
|
|
*/
|
|||
|
|
static saveToken(token, remember = false) {
|
|||
|
|
try {
|
|||
|
|
const storage = remember ? localStorage : sessionStorage;
|
|||
|
|
storage.setItem(this.TOKEN_KEY, token);
|
|||
|
|
|
|||
|
|
// 解析token获取过期时间
|
|||
|
|
const payload = this.parseToken(token);
|
|||
|
|
if (payload && payload.exp) {
|
|||
|
|
storage.setItem(this.TOKEN_KEY + '_exp', payload.exp.toString());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('Token saved successfully');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to save token:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取Token
|
|||
|
|
* @returns {string|null} Token或null
|
|||
|
|
*/
|
|||
|
|
static getToken() {
|
|||
|
|
try {
|
|||
|
|
// 优先从sessionStorage获取
|
|||
|
|
let token = sessionStorage.getItem(this.TOKEN_KEY);
|
|||
|
|
|
|||
|
|
// 如果sessionStorage没有,从localStorage获取
|
|||
|
|
if (!token) {
|
|||
|
|
token = localStorage.getItem(this.TOKEN_KEY);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查token是否过期
|
|||
|
|
if (token && this.isTokenExpired(token)) {
|
|||
|
|
this.removeToken();
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return token;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to get token:', error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 移除Token
|
|||
|
|
*/
|
|||
|
|
static removeToken() {
|
|||
|
|
try {
|
|||
|
|
sessionStorage.removeItem(this.TOKEN_KEY);
|
|||
|
|
sessionStorage.removeItem(this.TOKEN_KEY + '_exp');
|
|||
|
|
localStorage.removeItem(this.TOKEN_KEY);
|
|||
|
|
localStorage.removeItem(this.TOKEN_KEY + '_exp');
|
|||
|
|
|
|||
|
|
// 同时清除用户信息
|
|||
|
|
this.removeUser();
|
|||
|
|
|
|||
|
|
console.log('Token removed successfully');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to remove token:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查Token是否有效
|
|||
|
|
* @returns {boolean} 是否有效
|
|||
|
|
*/
|
|||
|
|
static isTokenValid() {
|
|||
|
|
const token = this.getToken();
|
|||
|
|
return token !== null && !this.isTokenExpired(token);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查Token是否过期
|
|||
|
|
* @param {string} token - JWT Token
|
|||
|
|
* @returns {boolean} 是否过期
|
|||
|
|
*/
|
|||
|
|
static isTokenExpired(token) {
|
|||
|
|
try {
|
|||
|
|
const payload = this.parseToken(token);
|
|||
|
|
if (!payload || !payload.exp) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// JWT的exp是秒级时间戳,JavaScript的Date.now()是毫秒级
|
|||
|
|
const currentTime = Math.floor(Date.now() / 1000);
|
|||
|
|
return payload.exp < currentTime;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to check token expiration:', error);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 解析JWT Token
|
|||
|
|
* @param {string} token - JWT Token
|
|||
|
|
* @returns {object|null} 解析后的payload
|
|||
|
|
*/
|
|||
|
|
static parseToken(token) {
|
|||
|
|
try {
|
|||
|
|
const parts = token.split('.');
|
|||
|
|
if (parts.length !== 3) {
|
|||
|
|
throw new Error('Invalid token format');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const payload = parts[1];
|
|||
|
|
const decoded = atob(payload.replace(/_/g, '/').replace(/-/g, '+'));
|
|||
|
|
return JSON.parse(decoded);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to parse token:', error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 保存用户信息
|
|||
|
|
* @param {object} user - 用户信息
|
|||
|
|
* @param {boolean} remember - 是否记住登录状态
|
|||
|
|
*/
|
|||
|
|
static saveUser(user, remember = false) {
|
|||
|
|
try {
|
|||
|
|
const storage = remember ? localStorage : sessionStorage;
|
|||
|
|
storage.setItem(this.USER_KEY, JSON.stringify(user));
|
|||
|
|
console.log('User info saved successfully');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to save user info:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取用户信息
|
|||
|
|
* @returns {object|null} 用户信息或null
|
|||
|
|
*/
|
|||
|
|
static getUser() {
|
|||
|
|
try {
|
|||
|
|
// 优先从sessionStorage获取
|
|||
|
|
let userStr = sessionStorage.getItem(this.USER_KEY);
|
|||
|
|
|
|||
|
|
// 如果sessionStorage没有,从localStorage获取
|
|||
|
|
if (!userStr) {
|
|||
|
|
userStr = localStorage.getItem(this.USER_KEY);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return userStr ? JSON.parse(userStr) : null;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to get user info:', error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 移除用户信息
|
|||
|
|
*/
|
|||
|
|
static removeUser() {
|
|||
|
|
try {
|
|||
|
|
sessionStorage.removeItem(this.USER_KEY);
|
|||
|
|
localStorage.removeItem(this.USER_KEY);
|
|||
|
|
console.log('User info removed successfully');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to remove user info:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 保存刷新Token
|
|||
|
|
* @param {string} refreshToken - 刷新Token
|
|||
|
|
*/
|
|||
|
|
static saveRefreshToken(refreshToken) {
|
|||
|
|
try {
|
|||
|
|
localStorage.setItem(this.REFRESH_TOKEN_KEY, refreshToken);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to save refresh token:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取刷新Token
|
|||
|
|
* @returns {string|null} 刷新Token或null
|
|||
|
|
*/
|
|||
|
|
static getRefreshToken() {
|
|||
|
|
try {
|
|||
|
|
return localStorage.getItem(this.REFRESH_TOKEN_KEY);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to get refresh token:', error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 移除刷新Token
|
|||
|
|
*/
|
|||
|
|
static removeRefreshToken() {
|
|||
|
|
try {
|
|||
|
|
localStorage.removeItem(this.REFRESH_TOKEN_KEY);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Failed to remove refresh token:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 清除所有认证信息
|
|||
|
|
*/
|
|||
|
|
static clearAll() {
|
|||
|
|
this.removeToken();
|
|||
|
|
this.removeUser();
|
|||
|
|
this.removeRefreshToken();
|
|||
|
|
console.log('All auth data cleared');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取Token头部信息用于HTTP请求
|
|||
|
|
* @returns {object|null} Authorization头部或null
|
|||
|
|
*/
|
|||
|
|
static getAuthHeader() {
|
|||
|
|
const token = this.getToken();
|
|||
|
|
return token ? { 'Authorization': `Bearer ${token}` } : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查用户是否已登录
|
|||
|
|
* @returns {boolean} 是否已登录
|
|||
|
|
*/
|
|||
|
|
static isLoggedIn() {
|
|||
|
|
return this.isTokenValid() && this.getUser() !== null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取Token剩余有效时间(秒)
|
|||
|
|
* @returns {number} 剩余秒数,-1表示已过期或无效
|
|||
|
|
*/
|
|||
|
|
static getTokenRemainingTime() {
|
|||
|
|
const token = this.getToken();
|
|||
|
|
if (!token) return -1;
|
|||
|
|
|
|||
|
|
const payload = this.parseToken(token);
|
|||
|
|
if (!payload || !payload.exp) return -1;
|
|||
|
|
|
|||
|
|
const currentTime = Math.floor(Date.now() / 1000);
|
|||
|
|
const remainingTime = payload.exp - currentTime;
|
|||
|
|
|
|||
|
|
return remainingTime > 0 ? remainingTime : -1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导出供其他模块使用
|
|||
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|||
|
|
module.exports = TokenManager;
|
|||
|
|
}
|