基于 vuex + vue-router 实现权限路由

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();
    }
  });
}
复制代码

5.参考资料

6.案例代码

完整案例代码

猜你喜欢

转载自juejin.im/post/7048457225542565902