Web:访问令牌 10 分钟;活跃时自动轮换刷新令牌;连续无操作 30 分钟后清除登录并跳转登录页。 App:会话窗口 3 天;打开 App、恢复前台或请求接口时自动刷新并重新顺延 3 天。 普通登录和 SSO 使用同一策略。 刷新令牌只以 SHA-256 摘要入库,每次刷新都会轮换,旧令牌无法再次使用;退出登录会吊销刷新令牌。 网络临时故障不会误清登录状态,多标签页同时刷新也做了竞争处理。
93 lines
2.4 KiB
TypeScript
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,
|
|
}
|
|
})
|