前言
Vue.js 中的路由权限涉及控制用户在访问网页应用程序中的不同页面时的权限限制和控制。
通常情况下,网页应用可能包含公共页面和需要特定权限才能访问的受保护页面。路由权限机制允许开发者根据用户的登录状态、角色、权限等条件来动态地控制页面的访问。
这就好比是一个王国的权利分配游戏,在一个王国(或者说管理系统)中,通常有不同的角色,比如国王(开发人员)、大臣(管理员)、公民(普通用户)和外来者(游客)。每个角色在王国中有不同的权力和责任。国王可以根据需要为不同的角色分配特定的权限,确保王国的资源和事务得到有效管理和保护。
举例来说,所有人都可以参观王国的景象,这类似于登录、注册和首页这些公共页面,任何人都可以自由访问。然而,只有王国的公民才能享有使用王国资源的特权,这相当于一些功能页面只对已登录的用户开放。至于大臣,他们具备管理国家事务的权限,可以访问和管理一些敏感的管理页面,而游客则只能访问公共页面,无法享有其他特权。
在实际的权限路由实现中,开发者会利用 Vue Router 的路由配置和元信息(meta)字段来定义这些权限规则。通过全局导航守卫和动态路由生成,可以根据当前用户的角色或权限动态地控制页面的访问和展示。
1.为不同的路由设置权限标识
路由权限的设置通过 meta
属性中的 noAuth
和 permiss
字段进行控制:
-
noAuth: true
表示无需认证即可访问的页面。 -
permiss: "xx"
用于后续的权限控制,在用户登录后会检查用户的权限标识,决定是否可以访问某些页面。
js
const routes: RouteRecordRaw[] = [
{
path: "/",
redirect: "/dashboard", // 当访问根路径 '/' 时重定向到 '/dashboard'
},
{
path: "/",
name: "Home",
component: () => import("../views/home.vue"),
children: [
{
path: "/dashboard",
name: "dashboard",
meta: {
title: "首页",
noAuth: true, // 标记为无需认证即可访问的页面
},
component: () => import("../views/dashboard.vue"),
},
{
path: "/system-user",
name: "system-user",
meta: {
title: "用户管理",
permiss: "11", // 权限标识,用于后续的权限控制
},
component: () => import("../views/system-user.vue"), /
},
{
path: "/table",
name: "basetable",
meta: {
title: "基础表格",
permiss: "31", // 权限标识,用于后续的权限控制
},
component: () => import("../views/basetable.vue"),
},
],
},
{
path: "/login",
meta: {
title: "登录",
noAuth: true, // 标记为无需认证即可访问的页面
},
component: () => import("../views/login.vue"),
},
{
path: "/403", // 权限不足页面路径
meta: {
title: "403",
noAuth: true, // 标记为无需认证即可访问的页面
},
component: () => import("../views/403.vue"),
},
{
path: "/404", // 页面不存在路径
meta: {
title: "404",
noAuth: true, // 标记为无需认证即可访问的页面
},
component: () => import("../views/404.vue"),
},
{
path: "/:path(.*)", // 捕获所有未匹配路径
redirect: "/404", // 重定向到 404 页面
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
2.为不同用户分配权限标识
在代码中可以使用了 Pinia 来定义一个名为 usePermissStore
的 Vuex-style store,用于管理用户权限信息。
-
定义 Pinia Store:
tsexport const usePermissStore = defineStore("permiss", () => { // 这里是 store 的具体定义 });
defineStore
函数用于创建一个 Pinia store。"permiss"
是该 store 的名称。
-
初始化默认分配的权限列表:
tsconst defaultList = { admin: [ "0", "1", "11","31" // 管理员的权限列表 ], user: [ "0", "1", "11" // 普通用户的权限列表 ], };
defaultList
对象定义了两种用户角色的权限列表:admin
和user
。每个角色都有一个包含权限标识的数组。
-
获取当前登录用户的用户角色:
tsconst userrole = localStorage.getItem("userrole"); const key = ref<string[]>([]); if (userrole) { key.value = userrole == "admin" ? defaultList.admin : defaultList.user; }
-
通过
localStorage.getItem("userrole")
获取存储在 localStorage 中的用户角色,这里假设用户登录后会将用户名存储在 localStorage 中。 -
key
是一个响应式的ref
,存储当前用户的权限列表。 -
如果
userrole
存在,根据用户角色来决定将key.value
设置为admin
或user
的权限列表。这里"admin"
用户角色表示管理员,"user"
用户角色表示普通用户。
-
-
权限设置方法
handleSet
:tsconst handleSet = (val: string[]) => { key.value = val; };
handleSet
是一个用于设置权限列表的方法。当需要更新用户权限时,调用handleSet
方法并传入新的权限数组val
,即可更新key.value
的值。
3.路由前置守卫鉴权
路由守卫就是作为这个王国的守护者,鉴定每一个用户的身份来判断用户是否拥有访问该路由的权限。
在 Vue Router 中,路由守卫是一组钩子函数,允许你在路由导航过程中对路由进行全局性的导航控制。
全局前置守卫 (beforeEach):
-
beforeEach 守卫用于在路由切换前进行身份验证和权限检查。
-
当用户尝试访问某个路由时,可以在这里验证用户的身份,检查是否有足够的权限访问目标页面。
-
示例中可以使用 to 和 from 参数来访问目标路径和当前路径。
ts
router.beforeEach((to, from, next) => {
const role = localStorage.getItem("userrole"); // 获取用户角色信息
const permissStore = usePermissStore(); // 获取权限状态管理器
if (!role && to.meta.noAuth !== true) {
next("/login"); // 未登录且目标页面需要登录,重定向到登录页
} else if (
typeof to.meta.permiss === "string" &&
!permissStore.key.includes(to.meta.permiss)
) {
next("/403"); // 已登录但缺少访问权限,重定向到403页面
} else {
next(); // 允许访问目标路由
}
});
if
-
!role
: 检查用户角色信息是否不存在,通常意味着用户未登录或者登录信息已过期。 -
to.meta.noAuth !== true
: 检查目标路由的meta
信息中是否明确指示该页面需要登录。如果noAuth
不为true
,则表示页面需要登录。 -
如果满足以上两个条件,通过
next("/login")
将用户重定向到登录页,因为用户未登录且目标页面要求登录。
else if
-
typeof to.meta.permiss === "string"
: 检查目标路由的meta
信息中是否定义了permiss
字段,并且其类型是字符串,通常用于表示访问该页面是否需要权限标识。 -
!permissStore.key.includes(to.meta.permiss)
: 检查当前用户的权限状态管理器中是否包含目标路由所需的权限标识。 -
如果用户已登录但不具备访问目标页面所需的权限,通过
next("/403")
将用户重定向到403页面,表示权限不足。
总结
通过以上的示例和比喻,你是否理解了vue权限路由呢,懂了的小伙伴点个赞,有疑问的小伙伴评论区留言,当然小编作为一个初学者,没有太多实战经验,欢迎大家提出更多宝贵的建议。