滑动续期与自动刷新:
Web:访问令牌 10 分钟;活跃时自动轮换刷新令牌;连续无操作 30 分钟后清除登录并跳转登录页。 App:会话窗口 3 天;打开 App、恢复前台或请求接口时自动刷新并重新顺延 3 天。 普通登录和 SSO 使用同一策略。 刷新令牌只以 SHA-256 摘要入库,每次刷新都会轮换,旧令牌无法再次使用;退出登录会吊销刷新令牌。 网络临时故障不会误清登录状态,多标签页同时刷新也做了竞争处理。
This commit is contained in:
+36
-18
@@ -1,6 +1,12 @@
|
||||
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
|
||||
@@ -12,54 +18,66 @@ export interface CurrentUser {
|
||||
}
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const token = ref(localStorage.getItem('jiaowu_token') ?? '')
|
||||
const saved = localStorage.getItem('jiaowu_user')
|
||||
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 })
|
||||
const { data } = await http.post('/auth/login', {
|
||||
userName,
|
||||
password,
|
||||
isNativeApp: isNativeApp(),
|
||||
})
|
||||
token.value = data.token
|
||||
user.value = data.user
|
||||
localStorage.setItem('jiaowu_token', data.token)
|
||||
localStorage.setItem('jiaowu_user', JSON.stringify(data.user))
|
||||
window.dispatchEvent(new Event('mingxu-auth-changed'))
|
||||
saveAuthSession(data)
|
||||
}
|
||||
|
||||
async function exchangeSso(code: string) {
|
||||
const { data } = await http.post('/auth/sso/exchange', { code })
|
||||
const { data } = await http.post('/auth/sso/exchange', {
|
||||
code,
|
||||
isNativeApp: isNativeApp(),
|
||||
})
|
||||
token.value = data.token
|
||||
user.value = data.user
|
||||
localStorage.setItem('jiaowu_token', data.token)
|
||||
localStorage.setItem('jiaowu_user', JSON.stringify(data.user))
|
||||
window.dispatchEvent(new Event('mingxu-auth-changed'))
|
||||
saveAuthSession(data)
|
||||
}
|
||||
|
||||
async function bindSso(code: string, userName: string, password: string) {
|
||||
const { data } = await http.post('/auth/sso/bind', { code, userName, password })
|
||||
const { data } = await http.post('/auth/sso/bind', {
|
||||
code,
|
||||
userName,
|
||||
password,
|
||||
isNativeApp: isNativeApp(),
|
||||
})
|
||||
token.value = data.token
|
||||
user.value = data.user
|
||||
localStorage.setItem('jiaowu_token', data.token)
|
||||
localStorage.setItem('jiaowu_user', JSON.stringify(data.user))
|
||||
window.dispatchEvent(new Event('mingxu-auth-changed'))
|
||||
saveAuthSession(data)
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
if (!token.value) return
|
||||
const { data } = await http.get('/auth/me')
|
||||
user.value = data
|
||||
localStorage.setItem('jiaowu_user', JSON.stringify(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
|
||||
localStorage.removeItem('jiaowu_token')
|
||||
localStorage.removeItem('jiaowu_user')
|
||||
window.dispatchEvent(new Event('mingxu-auth-changed'))
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user