Jaasomn
Initial deployment
ceb3821
// 认证模块 - 处理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('认证模块已加载');