重构登陆登出,对齐dashboard的认证方式

This commit is contained in:
jingrow 2025-12-27 22:01:21 +08:00
parent fd70b4149d
commit f59809023a
4 changed files with 75 additions and 110 deletions

View File

@ -215,10 +215,8 @@ router.beforeEach(async (to, _from, next) => {
const authStore = useAuthStore() const authStore = useAuthStore()
// 如果正在前往登录页,不需要初始化认证(避免重新设置状态) // 初始化认证状态(从 cookie 读取)
if (!authStore.isAuthenticated && to.path !== '/login' && to.path !== '/signup') { await authStore.initAuth()
await authStore.initAuth()
}
if (to.path.startsWith('/tools/') && to.name !== 'Tools') { if (to.path.startsWith('/tools/') && to.name !== 'Tools') {
// 如果路由已经匹配,直接通过 // 如果路由已经匹配,直接通过

View File

@ -1,8 +1,3 @@
export interface LoginResponse {
message: string
user: UserInfo
}
export interface UserInfo { export interface UserInfo {
id: string id: string
username: string username: string
@ -33,7 +28,7 @@ export function isCookieExpired(): boolean {
return !sessionCookie return !sessionCookie
} }
export const loginApi = async (username: string, password: string): Promise<LoginResponse> => { export const loginApi = async (username: string, password: string): Promise<void> => {
const response = await fetch(`/api/action/login`, { const response = await fetch(`/api/action/login`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -52,35 +47,8 @@ export const loginApi = async (username: string, password: string): Promise<Logi
throw new Error(errorData.detail || errorData.message || errorData.exc || '登录请求失败') throw new Error(errorData.detail || errorData.message || errorData.exc || '登录请求失败')
} }
const data = await response.json() // dashboard 登录接口成功后会设置 cookie不需要返回数据
// 登录状态通过 cookie 判断
// dashboard 登录接口成功后会设置 cookie返回的数据可能不包含 user 对象
// 需要通过 cookie 获取用户信息
// 登录成功,尝试获取用户信息
try {
const userInfo = await getUserInfoApi()
return { message: data.message || 'Logged In', user: userInfo }
} catch (error: any) {
// 如果获取用户信息失败,但登录成功,尝试从 cookie 获取基本信息
const sessionUser = getSessionUser()
if (sessionUser) {
// 返回基本用户信息
return {
message: data.message || 'Logged In',
user: {
id: sessionUser,
username: sessionUser,
email: username.includes('@') ? username : '',
avatar: '',
first_name: '',
last_name: '',
user_type: ''
}
}
}
// 如果都失败了,抛出错误
throw new Error(error.message || '登录成功但获取用户信息失败')
}
} }
// 获取用户信息 // 获取用户信息

View File

@ -16,26 +16,46 @@ export interface User {
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
const user = ref<User | null>(null) const user = ref<User | null>(null)
const loading = ref(false) const loading = ref(false)
const isAuthenticated = ref(false)
const isLoggedIn = computed(() => isAuthenticated.value && !!user.value) // 直接从 cookie 获取用户,与 dashboard 对齐
const getSessionUser = () => {
const cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
const sessionUser = cookies.get('user_id')
if (!sessionUser || sessionUser === 'Guest') {
return null
}
return sessionUser
}
// 登录状态完全依赖 cookie与 dashboard 对齐
const isLoggedIn = computed(() => {
const sessionUser = getSessionUser()
return !!sessionUser
})
const login = async (username: string, password: string) => { const login = async (username: string, password: string) => {
loading.value = true loading.value = true
try { try {
const response = await loginApi(username, password) await loginApi(username, password)
if (response.user) { // 登录成功后,从 cookie 获取用户信息
user.value = response.user const sessionUser = getSessionUser()
isAuthenticated.value = true if (sessionUser) {
user.value = {
id: sessionUser,
username: sessionUser,
email: username.includes('@') ? username : '',
avatar: '',
first_name: '',
last_name: '',
user_type: ''
}
// 保存登录状态到localStorage // 登录成功后直接跳转,与 dashboard 对齐
localStorage.setItem('jingrow_user', JSON.stringify(response.user)) window.location.href = '/'
localStorage.setItem('jingrow_authenticated', 'true') return { success: true }
return { success: true, user: response.user }
} else { } else {
return { success: false, error: response.message || '登录失败' } return { success: false, error: '登录失败' }
} }
} catch (error: any) { } catch (error: any) {
console.error('登录错误:', error) console.error('登录错误:', error)
@ -51,79 +71,59 @@ export const useAuthStore = defineStore('auth', () => {
} catch (error) { } catch (error) {
console.error('登出错误:', error) console.error('登出错误:', error)
} finally { } finally {
// 清除本地状态(先清除状态,再跳转) // 清除本地状态
user.value = null user.value = null
isAuthenticated.value = false
localStorage.removeItem('jingrow_user') localStorage.removeItem('jingrow_user')
localStorage.removeItem('jingrow_authenticated') localStorage.removeItem('jingrow_authenticated')
// 使用 window.location 强制跳转,避免路由守卫干扰 // 登出后重新加载页面,与 dashboard 对齐
window.location.href = '/login' window.location.reload()
} }
} }
const initAuth = async () => { const initAuth = async () => {
// 检查user_id是否为Guestcookie过期时后端会设置为Guest // 直接从 cookie 获取用户,与 dashboard 对齐
const cookies = new URLSearchParams(document.cookie.split('; ').join('&')) const sessionUser = getSessionUser()
const userId = cookies.get('user_id') if (sessionUser) {
if (userId === 'Guest') { // 从 localStorage 恢复用户信息(如果有)
// user_id是Guest说明cookie已过期清除本地状态 const savedUser = localStorage.getItem('jingrow_user')
if (isAuthenticated.value) { if (savedUser) {
await logout() try {
} user.value = JSON.parse(savedUser)
return } catch {
} // 如果解析失败,使用基本信息
user.value = {
// 首先检查session cookie是否存在 id: sessionUser,
if (!isCookieExpired()) { username: sessionUser,
try { email: '',
const userInfo = await getUserInfoApi() avatar: '',
user.value = userInfo first_name: '',
isAuthenticated.value = true last_name: '',
user_type: ''
// 更新localStorage }
localStorage.setItem('jingrow_user', JSON.stringify(userInfo))
localStorage.setItem('jingrow_authenticated', 'true')
return
} catch (error: any) {
console.error('验证用户信息失败:', error)
if (error.status === 401 || error.status === 403 || error.message?.includes('过期')) {
await logout()
} }
return } else {
} // 没有缓存,使用基本信息
} user.value = {
id: sessionUser,
// session cookie不存在检查localStorage username: sessionUser,
const savedUser = localStorage.getItem('jingrow_user') email: '',
const savedAuth = localStorage.getItem('jingrow_authenticated') avatar: '',
first_name: '',
if (savedUser && savedAuth === 'true') { last_name: '',
try { user_type: ''
user.value = JSON.parse(savedUser)
isAuthenticated.value = true
// 验证用户信息是否仍然有效
const userInfo = await getUserInfoApi()
user.value = userInfo
localStorage.setItem('jingrow_user', JSON.stringify(userInfo))
} catch (error: any) {
console.error('验证用户信息失败:', error)
if (error.status === 401 || error.status === 403 || error.message?.includes('过期')) {
await logout()
} else {
logout()
} }
} }
} else { } else {
if (isAuthenticated.value) { // 未登录,清除状态
await logout() user.value = null
} localStorage.removeItem('jingrow_user')
localStorage.removeItem('jingrow_authenticated')
} }
} }
const updateUserInfo = async () => { const updateUserInfo = async () => {
if (!isAuthenticated.value) return if (!isLoggedIn.value) return
try { try {
const userInfo = await getUserInfoApi() const userInfo = await getUserInfoApi()
@ -141,7 +141,6 @@ export const useAuthStore = defineStore('auth', () => {
return { return {
user, user,
loading, loading,
isAuthenticated,
isLoggedIn, isLoggedIn,
login, login,
logout, logout,

View File

@ -229,7 +229,7 @@ const handleSignup = async () => {
message.success(t('Sign up successful')) message.success(t('Sign up successful'))
if (result.user) { if (result.user) {
authStore.user = result.user authStore.user = result.user
authStore.isAuthenticated = true // cookie
localStorage.setItem('jingrow_user', JSON.stringify(result.user)) localStorage.setItem('jingrow_user', JSON.stringify(result.user))
localStorage.setItem('jingrow_authenticated', 'true') localStorage.setItem('jingrow_authenticated', 'true')
router.push('/') router.push('/')