1.序言
在访问控制的实践中,存在【用户,角色,权限】这三个范畴。用户拥有某个角色,某个角色拥有某种权限。需要阐释的是权限的含义。权限就是对资源的访问控制。从前端的角度出发,权限可以分为页面的访问权限,数据的操作权限。这篇博客讲述的是如何基于用户的角色来控制对页面的访问。
首先来看一下路由表。
2.路由表
案例有三个页面,分别是首页,设计器页面,异常页面。当用户的角色是 user 时可以访问首页,游客不可以访问。当用户的角色是 admin 时可以访问设计器页面,其余不具有 admin 角色的用户不可以访问。页面的权限信息挂载在路由的 meta 信息中。
const router = new VueRouter({
mode: "hash",
routes: [
{
path: "/home",
name: "Home",
component: () => import("../pages/home.vue"),
meta: {
title: "首页",
roles: ["user"],
},
},
{
path: "/designer",
name: "Designer",
component: () => import("../pages/designer.vue"),
meta: {
title: "设计器",
roles: ["admin"],
},
},
{
path: "/auth-error",
name: "AuthError",
component: () => import("../components/auth-error.vue"),
meta: {
title: "没有权限"
},
},
{
path: "/",
redirect: "/home",
},
],
});
复制代码
3.导航守卫
当用户访问任何一个页面前都要被拦截,拦截的目的是检查用户是否具有访问该页面的权限。一个只有 user 角色的用户是不被允许访问设计器页面的。拦截的逻辑如下:
router.beforeEach((to, from, next) => {
const userRoles = getUserRoles();
const requiredRoles = to.meta.roles || [];
if (requiredRoles.length > 0) {
if (requiredRoles.some((role) => userRoles.includes(role))) {
next();
} else {
next('/auth-error');
}
} else {
next();
}
});
复制代码
这里有一个问题,如何在路由插件中获取用户的角色呢?用户的信息一般保存在 store 中。因此,这个问题可以进一步提炼:如何在 vue-router 当中获取 vuex 的信息
。
4.状态插件
Vuex 的 store 接受 plugins
选项,Vuex 插件就是一个函数,它接收 store 作为唯一参数。
const store = new Vuex.Store({
state: {
...
},
getters: {
...
},
mutations: {
...
},
actions: {
...
},
plugins: [
authRouterPlugin
]
});
复制代码
authRouterPlugin 插件的作用就是拦截路由的改变,判断当前用户是否有访问目标路由的权限。如果有权限就放行,如果没有权限,那么跳转到错误提醒页面。完整代码如下:
import router from '@/route/index';
export default function authRouter(store) {
router.beforeEach((to, from, next) => {
const userRoles = store.getters.userRoles;
const requiredRoles = to.meta.roles || [];
if (requiredRoles.length > 0) {
if (requiredRoles.some((role) => userRoles.includes(role))) {
next();
} else {
next('/auth-error');
}
} else {
next();
}
});
}
复制代码