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:
100
frontend/app.js
100
frontend/app.js
@@ -827,39 +827,72 @@ handleDragLeave(e) {
|
|||||||
if (token && user) {
|
if (token && user) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.user = JSON.parse(user);
|
this.user = JSON.parse(user);
|
||||||
this.isLoggedIn = true;
|
|
||||||
|
|
||||||
// 从localStorage中的用户信息初始化存储相关字段
|
// 先验证token是否有效
|
||||||
this.storagePermission = this.user.storage_permission || 'sftp_only';
|
try {
|
||||||
this.storageType = this.user.current_storage_type || 'sftp';
|
const response = await axios.get(
|
||||||
this.localQuota = this.user.local_storage_quota || 0;
|
`${this.apiBase}/api/user/profile`,
|
||||||
this.localUsed = this.user.local_storage_used || 0;
|
{ 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;
|
||||||
|
|
||||||
// 加载最新的用户信息(异步更新)
|
// 更新localStorage中的用户信息
|
||||||
this.loadUserProfile();
|
localStorage.setItem('user', JSON.stringify(this.user));
|
||||||
|
|
||||||
// 启动定期检查用户配置
|
// 从最新的用户信息初始化存储相关字段
|
||||||
this.startProfileSync();
|
this.storagePermission = this.user.storage_permission || 'sftp_only';
|
||||||
// 读取上次停留的视图(需合法才生效)
|
this.storageType = this.user.current_storage_type || 'sftp';
|
||||||
const savedView = localStorage.getItem('lastView');
|
this.localQuota = this.user.local_storage_quota || 0;
|
||||||
let targetView = null;
|
this.localUsed = this.user.local_storage_used || 0;
|
||||||
if (savedView && this.isViewAllowed(savedView)) {
|
|
||||||
targetView = savedView;
|
console.log('[页面加载] Token验证成功,存储权限:', this.storagePermission, '存储类型:', this.storageType);
|
||||||
} else if (this.user.is_admin) {
|
|
||||||
targetView = 'admin';
|
// 启动定期检查用户配置
|
||||||
} else if (this.storagePermission === 'sftp_only' && !this.user.has_ftp_config) {
|
this.startProfileSync();
|
||||||
targetView = 'settings';
|
|
||||||
} else {
|
// 读取上次停留的视图(需合法才生效)
|
||||||
targetView = 'files';
|
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参数
|
// 检查URL参数
|
||||||
checkUrlParams() {
|
checkUrlParams() {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
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参数
|
// 检查URL参数
|
||||||
this.checkUrlParams();
|
this.checkUrlParams();
|
||||||
// 获取系统配置(上传限制等)
|
// 获取系统配置(上传限制等)
|
||||||
|
|||||||
Reference in New Issue
Block a user