addRoute实现路由权限
router.js
在router.js中在meta里使用role赋予路由权限,比如在下面的代码中我有四种用户user,A,B,C,我希望他们能访问的路由不同。其中登录页面是统一的,把他放在constantRoutes 中,404页面也是统一的,但是由于404页面必须最后加载,不然所有的页面都会被拦截到404,因此我们把他放在了asyncRoutes的最后一个。
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
import Layout from "@/layout";
export const asyncRoutes = [
{
path: "/dashboard",
component: Layout,
redirect: "/dashboard",
meta: {
title: "首页",
requiresAuth: true,
roles: ["user"],
},
children: [
{
path: "dashboard",
name: "Dashboard",
component: () => import("@/views/user/dashboard/index"),
meta: {
title: "首页",
requiresAuth: true,
},
},
],
},
{
path: "/downloadList",
component: Layout,
meta: {
title: "下载记录",
requiresAuth: true,
roles: ["user"],
},
children: [
{
path: "downloadList",
name: "DownloadList",
component: () => import("@/views/user/downloadRecord/index"),
meta: {
title: "下载记录",
requiresAuth: true,
roles: ["user"],
},
},
],
},
{
path: "/user_manage",
component: Layout,
meta: {
title: "用户管理",
roles: ["A", "B", "C"],
icon: "userManage",
},
children: [
{
path: "user",
name: "User",
component: () => import("@/views/admin/userManage/index"),
meta: {
title: "用户管理",
roles: ["A", "B", "C"],
icon: "userManage",
},
requiresAuth: true,
},
],
},
{
path: "/task_manage",
component: Layout,
meta: { title: "任务管理", roles: ["A", "B"], icon: "taskManage" },
children: [
{
path: "task",
name: "Task",
component: () => import("@/views/admin/taskManage/index"),
meta: { title: "任务管理", roles: ["A", "B"], icon: "taskManage" },
requiresAuth: true,
},
],
},
{
path: "/ssn_manage",
component: Layout,
meta: { title: "SSN管理", roles: ["A", "B"], icon: "announceManage" },
children: [
{
path: "ssn",
name: "SSN",
component: () => import("@/views/admin/ssnManage/index"),
meta: { title: "SSN管理", roles: ["A", "B"], icon: "announceManage" },
requiresAuth: true,
},
],
},
{ path: "*", redirect: "/404", hidden: true },
];
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/user/login/index"),
hidden: true,
},
];
const createRouter = () =>
new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes,
});
const router = createRouter();
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // reset router
}
export default router;
store/permission.js
这段代码主要是为了对路由进行验证
- 权限检查函数 (hasPermission): 该函数用于检查用户是否有权限访问特定路由,通过检查路由元数据中指定的角色信息。
- 异步路由过滤函数 (filterAsyncRoutes): 该函数基于用户的角色递归地过滤异步路由,以确保用户只能访问其具有权限的路由。
- 模块动作 (actions): 包含生成路由和清除路由两个动作。生成路由的动作会调用异步路由过滤函数,并将结果提交到状态中;清除路由的动作用于清空路由信息。
import { asyncRoutes, constantRoutes } from "@/router";
/**
* 用 meta.role判断当前路由是否有权限
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return route.meta.roles.some((item: any) => roles.includes(item));
} else {
return false;
}
}
/**
* 过滤路由
* @param routes asyncRoutes
* @param roles
*/
export function filterAsyncRoutes(routes, roles) {
const res = [];
routes.forEach((route) => {
const tmp = { ...route };
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles);
}
res.push(route);
} else {
hasPermission(roles, tmp);
}
});
return res;
}
const state = {
routes: [],
addRoutes: [],
};
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes;
state.routes = constantRoutes.concat(routes);
},
};
const actions = {
generateRoutes({ commit }, roles) {
return new Promise((resolve) => {
let accessedRoutes;
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
commit("SET_ROUTES", accessedRoutes);
resolve(accessedRoutes);
});
},
clearRoutes({ commit }) {
commit("SET_ROUTES", []);
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
permission.js
在这个文件里调用action过滤路由,获得符合当前角色的路由,可以直接写在main.js里,这里我们把他单独放在permission.js中,再从main.js引入。在这个文件里调用action过滤路由,获得符合当前角色的路由,可以直接写在main.js里,这里我们把他单独放在permission.js中,再从main.js引入。这里需要注意前面判断用户是否登录的逻辑可以自己定义但是在调用权限判定的action前一定要判断permission_routes是否已经有值,否则会进入无限循环。也就是
if (hasRoutes) {
next();
} 这一步。
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import { getUsername, getRole } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";
NProgress.configure({ showSpinner: false }); // NProgress Configuration
const whiteList = ["/login"]; // no redirect whitelist
router.beforeEach(async (to, from, next) => {
// start progress bar
NProgress.start();
document.title = getPageTitle(to.meta.title);
// set page title
const hasName = getUsername();
const hasRole = getRole();
if (hasName && hasRole) {
if (to.path === "/login") {
next();
NProgress.done();
} else {
const hasRoutes =
store.getters.permission_routes &&
store.getters.permission_routes.length > 0;//如果已经有permission_routes就不再遍历
if (hasRoutes) {
next();
} else {
try {
// generate accessible routes map based on roles
const accessRoutes = await store.dispatch(
"permission/generateRoutes",
[store.getters.roles]
);
router.addRoutes(accessRoutes);
next({ ...to, replace: true });
} catch (error) {
// remove token and go to login page to re-login
// await store.dispatch("user/resetToken");
Message.error(error || "Has Error");
next(`/login`);
NProgress.done();
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next();
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
});
router.afterEach(() => {
// finish progress bar
NProgress.done();
});
侧边栏
遍历之前过滤出来的permission_routers,通过vuex拿到之后动态v-for渲染。