Vue 全局守卫结合addRoute实现路由权限控制
程序员文章站
2022-03-02 09:42:24
...
思路就是前端写好全部的菜单信息,通过接口从后端拿相应权限。拿到之后使用全局守卫结合addRoute实现路由权限控制。
在日常开发中路由权限控制是经常遇到的,以下是我的部分代码实现:
名词解释:
全局守卫:
全局路由守卫每次都判断用户是否已经登录,没有登录则跳到登录页。已经登录(已经取得后台返回的用户的权限信息(角色之类的)),则判断当前要跳转的路由,用户是否有权限访问(根据路由名称到全部路由里找到对应的路由)。没有权限则跳到事先定义好的界面(403,404之类的)。
addRoute:
addRoutes
允许在应用初始化之后,动态的挂载路由。
实现:
第一步:
应用初始化的时候先挂载不需要权限控制的路由,比如登录页,404等错误页。
// router.js 初始化界面
import Vue from "vue";
import VueRouter from "vue-router";
import Layout from "../views/layout/Layout";
Vue.use(VueRouter);
const routes = [
{
path: "/login",
name: "login",
component: () => import("../views/login/login")
},
{
path: "/404",
name: "404",
component: () => import("../views/errorPage/404")
}
];
const router = new VueRouter({
mode: "history",
base: "/sdd/",
routes
});
export default router;
第二步:
全局路由守卫结合addRoute实现路由动态控制。
// permission.js 文件在main.js中直接引入
import router from "./router";
import NProgress from "nprogress";// 一个进度条控制组件
import "nprogress/nprogress.css";
import store from "./store";
import { generateMenu } from "./views/layout/components/utils/menu";
NProgress.configure({ showSpinner: false }); // 固定搭配
const whiteList = ["/login"]; // 白名单
router.beforeEach(async (to, from, next) => {
NProgress.start();
if (sessionStorage.token) {
if (to.path === "/login") {
next({ path: "/" });
NProgress.done();
} else {
// 获取当前用户信息
if (from.path === "/login" || !store.state.user.userInfo.username) {
const res = await store.dispatch("user/getUserInfo");
if (res.code !== 0) {
if (res.code !== 5002) {
sessionStorage.removeItem("token");
next({ path: "/login" });
NProgress.done();
}
} else {
// 获取用户权限
if (store.state.user.routes.length === 0) {
store
.dispatch("user/listMenus")
.then(res => {
// 路由遍历为树的形式
const routes = generateMenu(res.data) || [];
store.dispatch("user/setRoutes", routes);
routes.push({
path: "*",
redirect: "/404"
});
router.addRoutes(routes); // 动态添加可访问路由表
next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
})
.catch(() => {
sessionStorage.removeItem("token");
next({ path: "/login" });
NProgress.done();
});
} else {
next();
}
}
} else {
next();
}
}
} else {
// 白名单上的path 直接next()
if (whiteList.includes(to.path)) {
next();
} else {
next({ path: "/login" });
NProgress.done();
}
}
});
router.afterEach(() => {
NProgress.done();
});
generateMenu 方法实现:
import Layout from "../../Layout";
const menuMap = {
// 首页
home_page: {
path: "/",
icon: "Dashboard",
component: Layout
},
// 客户端用户
client_user_module: {
path: "/client-setting",
icon: "clientUser",
component: Layout
},
client_user_manager_submodule: {
path: "user",
icon: "clientUser",
component: () => import("../../../clientSetting/clientUser/clientUser")
},
client_user_template_submodule: {
path: "authority",
icon: "template",
component: () =>
import("../../../clientSetting/clientAuthority/clientAuthority")
},
client_user_announcement_submodule: {
path: "notice",
icon: "notice",
component: () =>
import("../../../clientSetting/clientSendNotice/clientSendNotice")
},
// 镜像管控
image_manager_module: {
path: "/system-image",
icon: "SystemImage",
component: Layout
},
image_manager_submodule: {
path: "management",
icon: "SystemImage",
component: () =>
import("../../../systemImage/systemImageManagement/systemImageManagement")
},
// 终端管控
terminal_manager_module: {
path: "/terminal-management",
icon: "Terminal",
component: Layout
},
terminal_manager_submodule: {
path: "management",
icon: "Terminal",
// prettier-ignore
component: () =>
import("../../../terminalManagement/terminalManagement/terminalManagement")
},
firmware_upgrade_submodule: {
path: "firmware-upgrade",
icon: "Upgrade",
component: () =>
import("../../../terminalManagement/firmwareUpgrade/firmwareUpgrade")
},
// 资产统计
asset_manager_module: {
path: "/asset-statistics",
icon: "Asset",
component: Layout
},
asset_hardware_submodule: {
path: "hardware",
icon: "Hardware",
component: () => import("../../../assetStatistics/hardware/hardware")
},
// 审计管理
audit_manager_module: {
path: "/audit-management",
icon: "Audit",
component: Layout
},
system_log_submodule: {
path: "systemLog",
icon: "systemLog",
component: () => import("../../../auditManagement/systemLog/systemLog")
},
web_log_submodule: {
path: "webLog",
icon: "webLog",
component: () => import("../../../auditManagement/webLog/webLog")
},
illegality_connect_log_submodule: {
path: "illegalOutreachLog",
icon: "illegalLog",
component: () =>
import("../../../auditManagement/illegalOutreachLog/illegalOutreachLog")
},
device_safe_log_submodule: {
path: "deviceSecurityLog",
icon: "deviceLog",
component: () =>
import("../../../auditManagement/deviceSecurityLog/deviceSecurityLog")
},
alarm_log_submodule: {
path: "alarm-log",
icon: "Alarm",
component: () => import("../../../auditManagement/alarmLog/alarmLog")
},
asset_hardware_change_log_submodule: {
path: "hardware-log",
icon: "HardwareLog",
component: () => import("../../../auditManagement/hardwareLog/hardwareLog")
},
power_control_log_submodule: {
path: "power-log",
icon: "Power",
component: () => import("../../../auditManagement/powerLog/powerLog")
},
// 系统设置
system_config_module: {
path: "/system-setting",
icon: "Setting",
component: Layout
},
global_config_submodule: {
path: "param",
icon: "params",
component: () => import("../../../systemSetting/systemParam/systemParam")
},
sysuser_manager_submodule: {
path: "user",
icon: "systemUser",
component: () => import("../../../systemSetting/systemUser/systemUser")
},
sysrole_manager_submodule: {
path: "role",
icon: "systemRole",
component: () => import("../../../systemSetting/systemRole/systemRole")
},
data_clear_submodule: {
path: "dataClean",
icon: "dataClean",
component: () =>
import("../../../systemSetting/systemDataClean/systemDataClean")
},
resource_center_submodule: {
path: "resource-center",
icon: "ResourceCenter",
component: () =>
import("../../../systemSetting/resourceCenter/resourceCenter")
},
// 系统帮助
system_help: {
path: "/help",
icon: "Help",
component: Layout
},
system_help_about: {
path: "about",
icon: "About",
component: () => import("../../../help/about/about")
}
};
export function generateMenu(menu) {
// 两级菜单
const travelMenu = menu => {
let routes = [];
for (let item of menu) {
let route = {};
route.name = item.moduleName;
route.path = menuMap[item.moduleId] && menuMap[item.moduleId].path;
route.component =
menuMap[item.moduleId] && menuMap[item.moduleId].component;
route.icon = menuMap[item.moduleId] && menuMap[item.moduleId].icon;
if (item.childModules && item.childModules.length > 0) {
route.children = travelMenu(item.childModules);
}
if (route.path && route.component) {
routes.push(route);
}
}
// 添加重定向
routes.forEach(item => {
if (item.path === "/") {
item.redirect = "/dashboard";
item.children = [
{
path: "dashboard",
component: () => import("../../../dashboard/dashboard"),
name: item.name
}
];
} else if (item.children) {
item.redirect = item.path + "/" + item.children[0].path;
}
});
return routes;
};
return travelMenu(menu);
}
上一篇: Vue学习笔记-初识Vue
下一篇: Vue父组件对子组件生命周期的监听