Files
sionrui/frontend/utils/token-manager.js
2025-11-12 22:45:29 +08:00

216 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()
}