mirror of
https://github.com/Cccc-owo/CheckInApp.git
synced 2026-06-17 05:56:29 +00:00
feat: implement JWT auth and optimize token validation
- Separate JWT login (21d) from check-in token - Unify check-in token validation with verify_checkin_authorization() - Update API docs for dual-token architecture
This commit is contained in:
@@ -34,49 +34,17 @@ client.interceptors.response.use(
|
||||
const { status, data } = error.response;
|
||||
|
||||
if (status === 401) {
|
||||
const errorDetail = data.detail || data.message || '';
|
||||
// JWT token 过期或无效:需要重新登录
|
||||
// 注意:打卡业务的 authorization token 过期不会影响网站登录状态
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
|
||||
// 检查用户是否设置了密码
|
||||
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
||||
const hasPassword = user.has_password || false;
|
||||
|
||||
// Token 过期的情况
|
||||
if (errorDetail.includes('过期')) {
|
||||
if (hasPassword) {
|
||||
// 有密码的用户:不强制退出,只显示警告
|
||||
// 不清除 localStorage,让用户继续使用
|
||||
console.warn('Token 已过期,但用户设置了密码,允许继续使用');
|
||||
|
||||
// 返回错误但不跳转登录页
|
||||
return Promise.reject({
|
||||
status,
|
||||
message: '登录凭证已过期,部分功能可能受限,建议刷新凭证',
|
||||
data,
|
||||
tokenExpired: true,
|
||||
});
|
||||
} else {
|
||||
// 没有密码的用户:必须重新登录
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
|
||||
// 延迟跳转,避免阻塞当前异步请求的错误处理
|
||||
setTimeout(() => {
|
||||
if (window.location.pathname !== '/login') {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}, 100);
|
||||
// 延迟跳转到登录页
|
||||
setTimeout(() => {
|
||||
if (window.location.pathname !== '/login') {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
} else {
|
||||
// 其他 401 错误(无效 Token 等):清除登录状态
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
|
||||
setTimeout(() => {
|
||||
if (window.location.pathname !== '/login') {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// 返回统一的错误对象
|
||||
|
||||
@@ -190,6 +190,7 @@
|
||||
<!-- QR Code Modal for Token Refresh -->
|
||||
<QRCodeModal
|
||||
v-model:visible="qrcodeModalVisible"
|
||||
:alias="authStore.user?.alias || ''"
|
||||
@success="handleQRCodeSuccess"
|
||||
@error="handleQRCodeError"
|
||||
/>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
v-model:value="qrcodeForm.alias"
|
||||
placeholder="请输入您的用户名"
|
||||
size="large"
|
||||
autocomplete="username"
|
||||
allow-clear
|
||||
@keyup.enter="handleQRCodeLogin"
|
||||
>
|
||||
@@ -66,6 +67,7 @@
|
||||
v-model:value="passwordForm.alias"
|
||||
placeholder="请输入您的用户名"
|
||||
size="large"
|
||||
autocomplete="username"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
@@ -79,6 +81,7 @@
|
||||
v-model:value="passwordForm.password"
|
||||
placeholder="请输入密码"
|
||||
size="large"
|
||||
autocomplete="current-password"
|
||||
@keyup.enter="handlePasswordLogin"
|
||||
>
|
||||
<template #prefix>
|
||||
@@ -235,46 +238,17 @@ const handlePasswordLogin = async () => {
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
// 使用 authStore 保存认证信息
|
||||
const user = {
|
||||
id: response.user_id,
|
||||
alias: response.alias,
|
||||
role: response.role || 'user',
|
||||
is_approved: response.is_approved !== false,
|
||||
};
|
||||
// 保存 JWT token 和用户信息
|
||||
authStore.setAuth(response.token, response.user);
|
||||
|
||||
// 如果没有 authorization(测试账号),使用 user_id 作为认证凭据
|
||||
const authToken = response.authorization || `user_id:${response.user_id}`;
|
||||
authStore.setAuth(authToken, user);
|
||||
|
||||
// 只有当有真实 authorization 时才获取完整用户信息
|
||||
if (response.authorization) {
|
||||
try {
|
||||
await authStore.fetchCurrentUser();
|
||||
} catch (err) {
|
||||
console.warn('获取完整用户信息失败,使用基本信息:', err);
|
||||
// 即使失败也继续登录流程
|
||||
}
|
||||
} else {
|
||||
// 没有 authorization 的测试账号,提示用户需要扫码绑定
|
||||
message.info({
|
||||
content: '您正在使用密码登录模式。如需使用打卡功能,请先扫码绑定 QQ。',
|
||||
duration: 5,
|
||||
});
|
||||
}
|
||||
|
||||
// 如果有 Token 警告,显示提示
|
||||
// 如果有打卡 Token 警告,显示提示(不影响网站登录)
|
||||
if (response.token_warning && response.warning_message) {
|
||||
message.warning({
|
||||
content: response.warning_message,
|
||||
duration: 5,
|
||||
});
|
||||
} else if (response.authorization) {
|
||||
// 只有有 token 的用户才显示"欢迎回来"
|
||||
message.success(`欢迎回来,${response.alias}!`);
|
||||
} else {
|
||||
// 测试账号登录成功提示
|
||||
message.success(`登录成功,${response.alias}!`);
|
||||
message.success(`欢迎回来,${response.user.alias}!`);
|
||||
}
|
||||
|
||||
// 跳转到重定向页面或仪表盘
|
||||
|
||||
Reference in New Issue
Block a user