VueJS项目中如何限制X角色仅可访问指定个人详情页面
实现方案
你可以通过动态路由重定向+全局路由守卫组合实现需求,具体步骤如下:
1. 修改路由配置
首先把根路径的写死重定向改成动态逻辑,同时给路由添加meta字段标记权限要求:
const routes = [ { path: '/', name: 'Home', component: Dashboard, // 改成函数式动态重定向 redirect: to => { const user = localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : null // 若用户信息已初始化完成,也可直接从store中取值判断 if (user?.is_X) { return `/streamers/${user.id}/detail/` } return '/streamers/' }, children:[ { path: 'streamers/', name: 'Streamers', component: Streamers, meta: { // 标记该路由禁止X角色访问 forbidX: true } }, { path: 'streamers/:id/detail/', name: 'StreamerDetail', component: StreamerDetail, meta: { // 标记需要登录才能访问 requireAuth: true } }, ], }, { path: '/login', name: 'Login', component: Login, } ]
2. 添加全局路由守卫
在你的router/index.js文件中创建路由实例后,添加前置守卫做权限校验:
const router = createRouter({ routes }) router.beforeEach((to, from, next) => { // 登录页直接放行 if (to.name === 'Login') return next() // 未登录统一跳转到登录页 if (!store.getters.isAuthenticated) return next({ name: 'Login' }) const isX = store.state.auth.user?.is_X const currentUserId = store.state.auth.user?.id // 校验X角色禁止访问的路由 if (isX && to.meta.forbidX) { // 直接跳转到X角色自己的详情页 return next({ name: 'StreamerDetail', params: { id: currentUserId } }) } // 校验X角色只能访问自己的详情页 if (isX && to.name === 'StreamerDetail') { if (to.params.id !== String(currentUserId)) { // 访问其他人的详情页时,跳回自己的详情页或者自定义403页 return next({ name: 'StreamerDetail', params: { id: currentUserId } }) } } next() })
3. 调整Dashboard组件的异步逻辑
因为用户信息加载是异步操作,需要确保路由守卫执行时用户信息已经初始化,所以修改Dashboard的mounted逻辑为异步等待:
export default { name: "Dashboard.vue", data() { return { snackbar: { color: null, message: null, }, userLoaded: false } }, async mounted(){ // 等待cookie校验和token刷新完成 await this.$store.dispatch('checkCookiesOnInit') if (!this.$store.getters.isAuthenticated){ await this.$store.dispatch('refreshToken') } this.userLoaded = true // 用户信息加载完成后如果是X角色,主动跳转一次避免初始化时重定向失效 if (this.$store.state.auth.user?.is_X && this.$route.name === 'Streamers') { this.$router.push({ name: 'StreamerDetail', params: { id: this.$store.state.auth.user.id } }) } }, }
同时修改模板,用户信息加载完成前可以加loading避免闪屏:
<template> <div v-if="$store.getters.isAuthenticated && userLoaded"> .... </div> <div v-else>加载中...</div> </template>
补充说明
如果你的项目中用户信息是在refreshToken执行完成后才写入store,建议在路由守卫中加个等待逻辑,避免守卫执行时用户信息还没加载完成导致判断错误。
内容的提问来源于stack exchange,提问作者Milano
相关产品推荐
相关产品推荐

