Files
sionrui/frontend/utils/token-manager.js

216 lines
5.3 KiB
JavaScript
Raw Normal View History

2025-11-12 22:45:29 +08:00
import { useCache, CACHE_KEY, deleteTokenCache } from '../hooks/web/useCache'
/**
* Token 统一管理模块Monorepo 全局工具
*
* 这是项目中唯一的 token 管理入口所有 token 操作都应该通过此模块进行
*
* Token 存储优先级读取顺序
* 1. 手动输入的 dev token (sessionStorage)
* 2. 正式登录的 token (wsCache/localStorage)
* 3. 环境变量 VITE_DEV_TOKEN
*
* Token 存储位置
* - ACCESS_TOKEN/access_token: 访问令牌wsCache/localStorage
* - REFRESH_TOKEN/refresh_token: 刷新令牌wsCache/localStorage
* - DEV_MANUAL_TOKEN: 开发手动输入的tokensessionStorage
*/
// ==================== 常量定义 ====================
const DEV_MANUAL_TOKEN_KEY = 'DEV_MANUAL_TOKEN'
// Token 键名变体(支持大小写不同)
const TOKEN_KEYS = {
ACCESS: [CACHE_KEY.ACCESS_TOKEN, 'access_token'],
REFRESH: [CACHE_KEY.REFRESH_TOKEN, 'refresh_token']
}
// ==================== 缓存实例管理 ====================
let wsCache = null
/**
* 获取 wsCache 实例延迟初始化避免模块加载时出错
* @returns {Object} wsCache 实例
*/
function getCache() {
if (!wsCache) {
try {
wsCache = useCache().wsCache
} catch (e) {
console.warn('初始化 wsCache 失败:', e)
// 返回一个安全的空对象,避免后续调用出错
wsCache = {
get: () => null,
set: () => {},
delete: () => {}
}
}
}
return wsCache
}
/**
* 获取完整的 Authorization Header
* @returns {string} Bearer token 或空字符串
*/
export function getAuthHeader() {
const token = getToken()
return token ? `Bearer ${token}` : ''
}
/**
* 获取 token
* @returns {string} token 字符串
*/
export function getToken() {
// 1. 优先使用手动输入的 dev token
const manualToken = sessionStorage.getItem(DEV_MANUAL_TOKEN_KEY)
if (manualToken) {
return manualToken
}
// 2. 使用正式登录的 token从 wsCache 读取)
try {
const cache = getCache()
// 尝试所有可能的键名变体
for (const key of TOKEN_KEYS.ACCESS) {
const accessToken = cache.get(key)
if (accessToken) {
return accessToken
}
}
} catch (e) {
console.warn('获取 wsCache 失败:', e)
}
// 3. 兜底:环境变量中的 token
const envToken = import.meta?.env?.VITE_DEV_TOKEN
if (envToken) {
return envToken
}
return ''
}
/**
* 设置手动输入的 dev token
* @param {string} token
*/
export function setDevToken(token) {
if (token) {
sessionStorage.setItem(DEV_MANUAL_TOKEN_KEY, token)
} else {
sessionStorage.removeItem(DEV_MANUAL_TOKEN_KEY)
}
}
/**
* 获取手动输入的 dev token用于显示
* @returns {string}
*/
export function getDevToken() {
return sessionStorage.getItem(DEV_MANUAL_TOKEN_KEY) || ''
}
/**
* 设置访问令牌和刷新令牌
* @param {Object} tokens - token 对象
* @param {string} tokens.accessToken - 访问令牌
* @param {string} tokens.refreshToken - 刷新令牌
*/
export function setToken(tokens) {
if (!tokens || (!tokens.accessToken && !tokens.refreshToken)) {
console.warn('setToken: token 参数无效', tokens)
return
}
try {
const cache = getCache()
if (tokens.accessToken) {
cache.set(CACHE_KEY.ACCESS_TOKEN, tokens.accessToken)
}
if (tokens.refreshToken) {
cache.set(CACHE_KEY.REFRESH_TOKEN, tokens.refreshToken)
}
} catch (e) {
console.error('设置 token 失败:', e)
}
}
/**
* 获取刷新令牌
* @returns {string|null} 刷新令牌或 null
*/
export function getRefreshToken() {
try {
const cache = getCache()
// 尝试所有可能的键名变体
for (const key of TOKEN_KEYS.REFRESH) {
const token = cache.get(key)
if (token) {
return token
}
}
} catch (e) {
console.warn('获取 refresh token 失败:', e)
}
return null
}
/**
* 清除所有 token
* 清空所有可能的 token 存储位置确保完全清除
*/
export function clearAllTokens() {
try {
// 1. 清空 sessionStorage 中的 dev token
sessionStorage.removeItem(DEV_MANUAL_TOKEN_KEY)
} catch (e) {
console.warn('清除 sessionStorage token 失败:', e)
}
try {
// 2. 清空 wsCache (localStorage) 中的所有可能的 token 键名
// 使用统一的 deleteTokenCache 函数,保持与 useCache 的一致性
deleteTokenCache()
} catch (e) {
console.warn('清除 wsCache token 失败:', e)
}
try {
// 3. 清空 localStorage 中可能的 token兜底处理
// 注意wsCache 默认使用 localStorage但为了确保清除也直接操作 localStorage
const localStorageKeys = [
...TOKEN_KEYS.ACCESS,
...TOKEN_KEYS.REFRESH,
DEV_MANUAL_TOKEN_KEY
]
localStorageKeys.forEach(key => {
try {
localStorage.removeItem(key)
} catch (e) {
// 忽略单个键删除失败
}
})
} catch (e) {
console.warn('清除 localStorage token 失败:', e)
}
}
/**
* 删除 token别名兼容旧代码
* @deprecated 使用 clearAllTokens() 代替
*/
export function removeToken() {
clearAllTokens()
}
/**
* 获取访问令牌别名兼容旧代码
* @returns {string} token 字符串
*/
export function getAccessToken() {
return getToken()
}