fix: 修复token过期后仍显示已登录状态的问题

- 页面加载时先向服务器验证token是否有效
- 添加axios响应拦截器,任何API返回401时自动登出
- 新增handleTokenExpired方法统一处理token失效
- token失效时显示Toast提示用户重新登录

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-27 13:43:11 +08:00
parent 4f9b281039
commit ffed82a55c

View File

@@ -827,39 +827,72 @@ handleDragLeave(e) {
if (token && user) {
this.token = token;
this.user = JSON.parse(user);
this.isLoggedIn = true;
// 从localStorage中的用户信息初始化存储相关字段
this.storagePermission = this.user.storage_permission || 'sftp_only';
this.storageType = this.user.current_storage_type || 'sftp';
this.localQuota = this.user.local_storage_quota || 0;
this.localUsed = this.user.local_storage_used || 0;
// 先验证token是否有效
try {
const response = await axios.get(
`${this.apiBase}/api/user/profile`,
{ headers: { Authorization: `Bearer ${token}` } }
);
console.log('[页面加载] 存储权限:', this.storagePermission, '存储类型:', this.storageType);
if (response.data.success && response.data.user) {
// token有效更新用户信息
this.user = response.data.user;
this.isLoggedIn = true;
// 加载最新的用户信息(异步更新)
this.loadUserProfile();
// 更新localStorage中的用户信息
localStorage.setItem('user', JSON.stringify(this.user));
// 启动定期检查用户配置
this.startProfileSync();
// 读取上次停留的视图(需合法才生效)
const savedView = localStorage.getItem('lastView');
let targetView = null;
if (savedView && this.isViewAllowed(savedView)) {
targetView = savedView;
} else if (this.user.is_admin) {
targetView = 'admin';
} else if (this.storagePermission === 'sftp_only' && !this.user.has_ftp_config) {
targetView = 'settings';
} else {
targetView = 'files';
// 从最新的用户信息初始化存储相关字段
this.storagePermission = this.user.storage_permission || 'sftp_only';
this.storageType = this.user.current_storage_type || 'sftp';
this.localQuota = this.user.local_storage_quota || 0;
this.localUsed = this.user.local_storage_used || 0;
console.log('[页面加载] Token验证成功存储权限:', this.storagePermission, '存储类型:', this.storageType);
// 启动定期检查用户配置
this.startProfileSync();
// 读取上次停留的视图(需合法才生效)
const savedView = localStorage.getItem('lastView');
let targetView = null;
if (savedView && this.isViewAllowed(savedView)) {
targetView = savedView;
} else if (this.user.is_admin) {
targetView = 'admin';
} else if (this.storagePermission === 'sftp_only' && !this.user.has_ftp_config) {
targetView = 'settings';
} else {
targetView = 'files';
}
// 强制切换到目标视图并加载数据
this.switchView(targetView, true);
} else {
// 响应异常,清除登录状态
this.handleTokenExpired();
}
} catch (error) {
console.warn('[页面加载] Token验证失败:', error.response?.status || error.message);
// token无效或过期清除登录状态
this.handleTokenExpired();
}
// 强制切换到目标视图并加载数据
this.switchView(targetView, true);
}
},
// 处理token过期/失效
handleTokenExpired() {
console.log('[认证] Token已失效清除登录状态');
this.isLoggedIn = false;
this.user = null;
this.token = null;
localStorage.removeItem('token');
localStorage.removeItem('user');
localStorage.removeItem('lastView');
this.stopProfileSync();
},
// 检查URL参数
checkUrlParams() {
const urlParams = new URLSearchParams(window.location.search);
@@ -2374,6 +2407,23 @@ handleDragLeave(e) {
}
});
// 设置axios响应拦截器处理401错误token过期/失效)
axios.interceptors.response.use(
response => response,
error => {
if (error.response && error.response.status === 401) {
// 排除登录接口本身的401密码错误等
const isLoginApi = error.config?.url?.includes('/api/login');
if (!isLoginApi && this.isLoggedIn) {
console.warn('[认证] 收到401响应Token已失效');
this.handleTokenExpired();
this.showToast('warning', '登录已过期', '请重新登录');
}
}
return Promise.reject(error);
}
);
// 检查URL参数
this.checkUrlParams();
// 获取系统配置(上传限制等)