Vue3+Laravel前后端分离:未认证用户跳转登录页实现
实现未认证用户自动跳转登录页方案
1. 标记路由的认证规则
先修改路由配置,明确哪些页面需要登录才能访问,哪些页面仅允许未登录用户访问:
// router/index.js const routes = [ { path: '/', name: "Home", component: Home, meta: { authRequired: false, // 不需要认证 }, }, { path: '/admin', children:[ {path: 'dashboard', name: "Dashboard", component: Dashboard}, {path: 'users', name: "Users", component: Users}, {path: 'roles', name: "Roles", component: Roles}, {path: 'permissions', name: "Permissions", component: Permissions}, ], meta: { authRequired: true, // 所有子路由都需要认证 }, }, { path: '/login', name: "Login", component: Login, meta: { guestOnly: true, // 仅未登录用户可访问 }, }, { path: '/register', name: "Register", component: Register, meta: { guestOnly: true, }, }, { path: '/unauthorized', name: 'Unauthorized', component: Unauthorized, meta: { authRequired: false, }, } ];
2. 添加路由全局守卫
在router/index.js末尾添加全局前置守卫,每次路由跳转前检查用户认证状态:
// router/index.js import { useAuthStore } from '../stores/auth'; // 导入Pinia的auth store router.beforeEach(async (to, from, next) => { const authStore = useAuthStore(); // 如果用户状态未初始化(比如页面刷新后),先尝试获取用户信息 if (authStore.authUser === null) { try { await authStore.getUser(); } catch (error) { // 获取失败说明未登录,清空用户状态 authStore.authUser = null; } } // 处理需要认证的页面 if (to.meta.authRequired && !authStore.authUser) { next('/login'); // 未登录跳登录页 return; } // 处理仅允许未登录用户访问的页面(比如登录、注册) if (to.meta.guestOnly && authStore.authUser) { next('/admin/dashboard'); // 已登录跳后台首页 return; } // 其他情况正常跳转 next(); });
3. 修复Pinia的用户信息获取逻辑
修改store/auth.js中的getUser方法,添加错误捕获,避免未登录时axios请求报错:
// store/auth.js async getUser() { await this.getToken(); try { const data = await axios.get('/api/user'); this.authUser = data.data; this.userRoles = data.data.roles; this.userPermissions = data.data.permissions; } catch (error) { // 401或其他错误说明未登录,清空用户状态 this.authUser = null; this.userRoles = null; this.userPermissions = null; } }
同时给store注入router,解决原有action中this.router未定义的问题:
// store/auth.js actions: { // 添加初始化router的方法 initRouter(router) { this.router = router; }, // ...其他原有action }
在main.js中完成router注入:
// main.js import { createApp } from 'vue'; import { createPinia } from 'pinia'; import router from './router'; import { useAuthStore } from './stores/auth'; import App from './App.vue'; const app = createApp(App); const pinia = createPinia(); app.use(pinia); app.use(router); // 注入router到auth store const authStore = useAuthStore(); authStore.initRouter(router); app.mount('#app');
4. 页面初始化时验证用户状态
在App.vue的onMounted钩子中调用getUser,确保页面刷新后用户状态正确:
<!-- App.vue --> <script setup> import { onMounted } from 'vue'; import { useAuthStore } from './stores/auth'; const authStore = useAuthStore(); onMounted(async () => { // 页面加载后尝试获取用户信息 await authStore.getUser(); }); </script>
额外优化:Axios响应拦截器
添加Axios拦截器,当后端返回401(未认证)时自动跳登录页并清空用户状态:
// 在main.js或者单独的axios配置文件中 import axios from 'axios'; import { useAuthStore } from './stores/auth'; import router from './router'; axios.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { const authStore = useAuthStore(); authStore.authUser = null; authStore.userRoles = null; authStore.userPermissions = null; router.push('/login'); } return Promise.reject(error); } );
内容的提问来源于stack exchange,提问作者SCloud
相关产品推荐
相关产品推荐

