// 认证模块 - 处理token管理和API调用封装 /** * 认证管理类 */ class AuthManager { constructor() { this.tokenKey = 'authToken'; this.expiryKey = 'authTokenExpiry'; this.baseURL = window.location.origin; } /** * 获取存储的token */ getToken() { return localStorage.getItem(this.tokenKey); } /** * 获取token过期时间 */ getTokenExpiry() { const expiry = localStorage.getItem(this.expiryKey); return expiry ? parseInt(expiry) : null; } /** * 检查token是否有效 */ isTokenValid() { const token = this.getToken(); const expiry = this.getTokenExpiry(); if (!token) return false; // 如果设置了过期时间,检查是否过期 if (expiry && Date.now() > expiry) { this.clearToken(); return false; } return true; } /** * 保存token到本地存储 */ saveToken(token, rememberMe = false) { localStorage.setItem(this.tokenKey, token); if (rememberMe) { const expiryTime = Date.now() + (7 * 24 * 60 * 60 * 1000); // 7天 localStorage.setItem(this.expiryKey, expiryTime.toString()); } } /** * 清除token */ clearToken() { localStorage.removeItem(this.tokenKey); localStorage.removeItem(this.expiryKey); } /** * 登出 */ async logout() { this.clearToken(); window.location.href = '/login.html'; } } /** * API调用封装类 */ class ApiClient { constructor() { this.authManager = new AuthManager(); this.baseURL = window.location.origin; } /** * 获取带认证的请求头 */ getAuthHeaders() { const token = this.authManager.getToken(); return token ? { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } : { 'Content-Type': 'application/json' }; } /** * 处理401错误重定向到登录页 */ handleUnauthorized() { this.authManager.clearToken(); window.location.href = '/login.html'; } /** * 通用API请求方法 */ async request(endpoint, options = {}) { const url = `${this.baseURL}/api${endpoint}`; const headers = { ...this.getAuthHeaders(), ...options.headers }; const config = { ...options, headers }; try { const response = await fetch(url, config); // 如果是401错误,重定向到登录页 if (response.status === 401) { this.handleUnauthorized(); throw new Error('未授权访问'); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else { return await response.text(); } } catch (error) { if (error.message === '未授权访问') { // 已经在handleUnauthorized中处理了重定向 throw error; } console.error('API请求错误:', error); throw error; } } /** * GET请求 */ async get(endpoint, params = {}) { const queryString = new URLSearchParams(params).toString(); const url = queryString ? `${endpoint}?${queryString}` : endpoint; return this.request(url, { method: 'GET' }); } /** * POST请求 */ async post(endpoint, data = {}) { return this.request(endpoint, { method: 'POST', body: JSON.stringify(data) }); } /** * PUT请求 */ async put(endpoint, data = {}) { return this.request(endpoint, { method: 'PUT', body: JSON.stringify(data) }); } /** * DELETE请求 */ async delete(endpoint) { return this.request(endpoint, { method: 'DELETE' }); } /** * POST请求(支持FormData上传) */ async upload(endpoint, formData) { const url = `${this.baseURL}/api${endpoint}`; // 获取认证token const token = this.authManager.getToken(); const headers = {}; // 如果有token,添加Authorization头部 if (token) { headers['Authorization'] = `Bearer ${token}`; } // 对于FormData请求,不添加Content-Type头部,让浏览器自动设置 const config = { method: 'POST', headers, body: formData }; try { const response = await fetch(url, config); // 如果是401错误,重定向到登录页 if (response.status === 401) { this.handleUnauthorized(); throw new Error('未授权访问'); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else { return await response.text(); } } catch (error) { if (error.message === '未授权访问') { // 已经在handleUnauthorized中处理了重定向 throw error; } console.error('API请求错误:', error); throw error; } } } /** * 初始化认证检查 */ async function initAuth() { const authManager = new AuthManager(); // 检查是否已经有有效的token if (authManager.isTokenValid()) { // 验证token是否仍然有效(发送一个测试请求) try { const apiClient = new ApiClient(); await apiClient.get('/health'); return true; } catch (error) { // Token无效,清除并重定向到登录页 authManager.clearToken(); window.location.href = '/login.html'; return false; } } else { // 没有有效token,重定向到登录页 window.location.href = '/login.html'; return false; } } /** * 登出函数 */ async function logout() { const authManager = new AuthManager(); await authManager.logout(); } /** * 登录函数(供登录页面使用) */ async function login(password, rememberMe = false) { try { const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ password, rememberMe }) }); const data = await response.json(); if (data.success) { // 保存token const authManager = new AuthManager(); authManager.saveToken(data.token, rememberMe); return { success: true }; } else { return { success: false, message: data.message }; } } catch (error) { console.error('登录错误:', error); return { success: false, message: '登录失败,请检查网络连接' }; } } // 创建单例实例 const authManager = new AuthManager(); const apiClient = new ApiClient(); /** * 获取带认证的请求头(便捷函数) * @returns {Object} 包含认证信息的请求头 */ function getAuthHeaders() { return apiClient.getAuthHeaders(); } // 导出实例到 window(兼容旧代码) window.authManager = authManager; window.apiClient = apiClient; window.initAuth = initAuth; window.logout = logout; window.login = login; // 导出认证管理器类和API客户端类供其他模块使用 window.AuthManager = AuthManager; window.ApiClient = ApiClient; // ES6 模块导出 export { AuthManager, ApiClient, authManager, apiClient, initAuth, logout, login, getAuthHeaders }; console.log('认证模块已加载');