本篇介紹Vue Nuxt 3的前端登入狀態管理。
「Vue Nuxt 3 登入驗證」中已經對SSR路由(瀏覽器直接輸入網址)進行驗證檢查,但前端只在login頁面登入時做過一次驗證,但後續的SPA路由(登入後在頁面內點選<NuxtLink>連結或執行程式中的navigateTo)都沒有再進行驗證,且前端目前無從得知登入狀態,所以下面會加入驗證狀態以便前端進行判別。
事前要求
參考「Vue Nuxt 3 登入驗證」。
新增登入驗證狀態
在composables目錄下新增useAuth.ts,使用useState建立跨頁響應式共享狀態物件,名稱為"isLogin",初始值為false,此即為前端的[登入狀態],之後SPA路由時可用來判斷是否已通過驗證。
要注意useAuth只負責前端狀態的管理,且由於是存在Nuxt執行期間的記憶體中,重新整理瀏覽器時此狀態會被初始化,因此必須由後端SSR路由驗證成功後回填來同步。
composables/useAuth.ts
export const useAuth = () =>
useState<boolean>('isLogin', () => false)
登入時設定狀態
修改pages/login.vue,引入useAuth,登入成功後把登入狀態isLogin設為true。
pages/login.vue
<template>
<h1>登入</h1>
<!--...-->
</template>
<script setup lang="ts">
definePageMeta({
layout: 'auth'
})
import { ref } from 'vue'
import type { LoginResponse } from '~/types/auth'
const isLogin = useAuth()
const username = ref('')
const password = ref('')
const login = async () => {
try {
const { success, token } = await $fetch<LoginResponse>('/api/auth/login', {
method: 'POST',
body: { username: username.value, password: password.value }
})
if (success && token) {
isLogin.value = true // <--
navigateTo('/home')
}
} catch (err) {
alert('登入失敗,請稍後再試')
}
}
</script>
修改驗證Middleware
修改middleware/auth.global.ts,SPA路由時if (import.meta.client)檢查[登入狀態]isLogin,若未登入(isLogin == false)則導回[登入頁面];在SSR驗證通過後同步前端[登入狀態],必免重新整理瀏覽器時useAuth被初始化,導致client hydration的時候在SPA路由登入驗證時被返回[登入頁面]。
middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to) => {
if (to.path === "/login") return; // 登入頁面不用驗證
const isLogin = useAuth()
// 檢查SSR路由登入驗證
if (import.meta.server) {
const token = useCookie("token").value;
if (!token) {
return navigateTo("/login");
}
isLogin.value = true; // 同步前端登入狀態
}
// 檢查SPA路由登入驗證
if (import.meta.client) {
if (!isLogin.value) {
return navigateTo("/login");
}
}
});
接下來加入使用者角色和側邊選單的權限控管。
沒有留言:
張貼留言