Files
Academic-Affairs-System/web/src/stores/auth.ts
T
biss 5ec62a03ca 滑动续期与自动刷新:
Web:访问令牌 10 分钟;活跃时自动轮换刷新令牌;连续无操作 30 分钟后清除登录并跳转登录页。
App:会话窗口 3 天;打开 App、恢复前台或请求接口时自动刷新并重新顺延 3 天。
普通登录和 SSO 使用同一策略。
刷新令牌只以 SHA-256 摘要入库,每次刷新都会轮换,旧令牌无法再次使用;退出登录会吊销刷新令牌。
网络临时故障不会误清登录状态,多标签页同时刷新也做了竞争处理。
2026-08-03 19:20:39 +08:00

93 lines
2.4 KiB
TypeScript

import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import http from '../api/http'
import {
authStorageKeys,
clearAuthSession,
isNativeApp,
saveAuthSession,
} from '../auth/session'
export interface CurrentUser {
id: string
userName: string
displayName: string
roles: string[]
collegeId?: string
effectiveDataScope: 'Self' | 'Class' | 'College' | 'All'
}
export const useAuthStore = defineStore('auth', () => {
const token = ref(localStorage.getItem(authStorageKeys.token) ?? '')
const saved = localStorage.getItem(authStorageKeys.user)
const user = ref<CurrentUser | null>(saved ? JSON.parse(saved) : null)
const isLoggedIn = computed(() => Boolean(token.value))
const isSuperAdmin = computed(() => user.value?.roles.includes('SuperAdmin') ?? false)
async function login(userName: string, password: string) {
const { data } = await http.post('/auth/login', {
userName,
password,
isNativeApp: isNativeApp(),
})
token.value = data.token
user.value = data.user
saveAuthSession(data)
}
async function exchangeSso(code: string) {
const { data } = await http.post('/auth/sso/exchange', {
code,
isNativeApp: isNativeApp(),
})
token.value = data.token
user.value = data.user
saveAuthSession(data)
}
async function bindSso(code: string, userName: string, password: string) {
const { data } = await http.post('/auth/sso/bind', {
code,
userName,
password,
isNativeApp: isNativeApp(),
})
token.value = data.token
user.value = data.user
saveAuthSession(data)
}
async function refresh() {
if (!token.value) return
const { data } = await http.get('/auth/me')
user.value = data
localStorage.setItem(authStorageKeys.user, JSON.stringify(data))
}
function logout() {
const refreshToken = localStorage.getItem(authStorageKeys.refreshToken)
if (refreshToken) void http.post('/auth/logout', { refreshToken }).catch(() => undefined)
token.value = ''
user.value = null
clearAuthSession()
}
window.addEventListener('mingxu-auth-changed', () => {
token.value = localStorage.getItem(authStorageKeys.token) ?? ''
const currentUser = localStorage.getItem(authStorageKeys.user)
user.value = currentUser ? JSON.parse(currentUser) : null
})
return {
token,
user,
isLoggedIn,
isSuperAdmin,
login,
exchangeSso,
bindSso,
refresh,
logout,
}
})