当前位置: 首页 > news >正文

企业级Vue路由角色权限应该怎么做?

角色权限

角色权限,简单来说就是登录的用户能看到系统的哪些页面,不能看到系统的哪些页面。一般是后台管理系统才会涉及到如此复杂的角色权限。

对于 vue 技术栈,实现角色权限一般有两种方式。

第一种是利用 beforeEach 全局前置守卫。

第二种是利用 addRoutes 方法。

我们先来看看第一种

通过 beforeEach 实时监测用户权限

这种方案的核心就是首先在 routes 里面事先定义好路由的权限,然后在 beforeEach 全局前置守卫里面进行权限逻辑判断。看用户所拥有的角色和我们配置在路由里面的 roles 是否相匹配。匹配则允许进入,不匹配则重定向到无权限提示页面。

定义 routes

首先我们定义好系统的路由,对于非首页,我们一般都会使用路由懒加载。

在 meta 里面可以定义我们需要的元数据,这里需要加上我们路由的角色roles。也就是说进入该路由用户所需要具备的角色权限。如果没定义则代表任意角色都能进入。

js
复制代码
// router/routes.jsimport Home from "../views/Home.vue";const routes = [{path: "/",name: "Home",component: Home,meta: {needLogin: false, // 不需要登录title: "首页",},},{path: "/about", name: "About",component: () =>import(/* webpackChunkName: "about" */ "../views/About.vue"), // 路由懒加载meta: {needLogin: true, // 需要登录title: "关于",roles: ["admin", "manage"], // 该页面只有admin和普通管理员才能进入},},{path: "/nopermission", // 没权限就进入该页面name: "NoPermission",component: () =>import(/* webpackChunkName: "nopermission" */ "../views/NoPermission.vue"), // 路由懒加载meta: {needLogin: true, // 需要登录title: "暂无权限",},},{path: "/userlist", name: "UserList",component: () =>import(/* webpackChunkName: "userlist" */ "../views/UserList.vue"), // 路由懒加载meta: {needLogin: true, // 需要登录title: "用户管理",roles: ["admin"], // 该页面只有admin才能进入},},{path: "/login",name: "Login",component: () =>import(/* webpackChunkName: "login" */ "../views/Login.vue"), // 路由懒加载meta: {needLogin: false, // 不需要登录title: "登录",},},
];export default routes;

实例化 Router

然后创建路由,vue2vue3创建路由的时候稍有区别,但是在路由鉴权那块是通用的。

js
复制代码
// router/index.js// vue2 写法
import VueRouter from "vue-router";
import routes from "./routes"const router = new VueRouter({mode: "history",base: process.env.BASE_URL,routes,
});// vue3 写法
import { createRouter, createWebHistory } from "vue-router";
import routes from "./routes"const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes,
});

定义路由拦截鉴权逻辑

创建好路由后,我们可以来定义路由拦截的逻辑了,主要通过 beforeEach 全局前置守卫。因为只要页面发生跳转都会进入 beforeEach 全局前置守卫。

这里的核心逻辑就是判断前往的页面是否需要登录,需要登录就进一步判断当前系统是否有token,没有token则重定向到登录页

如果有token,则进一步判断是否有用户信息,如果没有用户信息就获取用户信息

有了用户信息后再判断进入页面需要的角色是否和用户信息里面的角色相匹配,匹配则进入页面,不匹配则进入系统的无权限提示页面。

js
复制代码
// router/index.js// vue2和vue3通用
router.beforeEach(async (to, from, next) => {// 如果需要登录if (to.meta.needLogin) {// 获取tokenconst token = localStorage.getItem("token");// 如果有token 则直接放行if (token) {// 获取用户信息,从store里面获取let userInfo = store.getters["getUserInfo"];// 如果没有用户信息就获取用户信息if (!userInfo) {userInfo = await store.dispatch("getUserInfoAction");}// 如果页面需要权限,并且用户角色不满足则去无权限提示页if (to.meta.roles && !to.meta.roles.includes(userInfo.role)) {return next("/nopermission");}next();} else {// 否则去登录页next("/login");}} else {// 不需要登录则直接放行next();}
});// 修改标题的工作可以放在全局后置守卫
router.afterEach((to, from) => {if (to.meta.title) {document.title = to.meta.title;}
});

我们再来看看 store 的逻辑

js
复制代码
import { createStore } from "vuex";export default createStore({state: {userInfo: null,},getters: {getUserInfo: (state) => state.userInfo,},mutations: {setUserInfo(state, payload) {state.userInfo = payload;},},actions: {async getUserInfoAction({ commit }) {// 模拟后端获取用户信息的apiconst getUserInfoApi = () => {return Promise.resolve({ role: "manage", name: "jack" }); // 假设角色为 manage};const userInfo = await getUserInfoApi();commit("setUserInfo", userInfo);return userInfo;},},
});

使用

创建完路由后需要在 main.js 导入使用

js
复制代码
import router from "./router";// vue2写法
new Vue({router,render: (h) => h(App),
}).$mount("#app");// vue3写法
const app = createApp(App);
app.use(router).mount("#app");

在没登录的情况下,去aboutuserlist页面都会重定向到登录页。

给本地添加token 模拟登录完成后,因为用户信息角色是 manage,所以去 about 是没问题的,去 userlist 则会重定向到没有权限页面。

总结

优点:

实现简单,路由的权限在 meta 的 roles 里面配置。用户信息里面只需要包含当前用户的角色。

缺点:

系统所拥有的角色必须事先知道,然后以死代码的形式配置在 routes 里面,不支持动态添加角色。适用于小型角色固定的系统。

通过 addRoutes 动态添加路由

这种方案的核心就是调用后端接口,返回当前用户角色所拥有的菜单,格式化成路由后通过 addRoutes 将这些路由动态添加到系统。

定义 routes

因为路由从后端获取,所以这里我们只需要定义基本通用路由,也就是不涉及到权限的路由。比如登录页、没权限页、首页。

js
复制代码
import Home from "../views/Home.vue";const routes = [{path: "/",name: "Home",component: Home,meta: {title: "首页",},},{path: "/nopermission", // 没权限就进入该页面name: "NoPermission",component: () =>import(/* webpackChunkName: "nopermission" */ "../views/NoPermission.vue"), // 路由懒加载meta: {title: "暂无权限",},},{path: "/login",name: "Login",component: () =>import(/* webpackChunkName: "login" */ "../views/Login.vue"), // 路由懒加载meta: {title: "登录",},},
];export default routes;

实例化 Router

然后创建路由,vue2vue3创建路由的时候稍有区别。

js
复制代码
// router/index.js// vue2 写法
import VueRouter from "vue-router";
import routes from "./routes"const router = new VueRouter({mode: "history",base: process.env.BASE_URL,routes,
});// vue3 写法
import { createRouter, createWebHistory } from "vue-router";
import routes from "./routes"const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes,
});

定义路由拦截鉴权逻辑

创建好路由后,我们就可以定义动态添加路由的逻辑啦。

这里的核心逻辑就是判断前往的页面是否在白名单内,不在白名单就进一步判断当前系统是否有token,没有token则重定向到登录页

如果有token,则进一步判断是否有用户菜单信息,如果没有用户菜单信息就获取用户菜单信息

有了用户菜单信息后,就先将菜单信息转换成前端路由需要的格式,然后通过addRoutes方法将路由动态添加到系统。

当用户前往不存在的路由时,路由的 name 属性会是 undefined,因此就重定向到无权限提示页面

js
复制代码
// router/index.js// vite创建的项目 使用这种方法实现动态加载
const modules = import.meta.glob("../views/*.vue");// 转换成 vue-router 需要的格式
const transformRoute = (menus) => {return menus.map((menu) => {return {path: menu.path,name: menu.name,component: modules[menu.component],meta: {title: menu.title,},};});
};// vue3需要手动实现该方法
const addRoutes = (routes) => {routes.forEach((route) => {router.addRoute(route);});
};// 白名单页面,不需要权限
const whiteLists = ["/login", "/"];router.beforeEach(async (to, from, next) => {// 是否是白名单if (!whiteLists.includes(to.path)) {// 获取tokenconst token = localStorage.getItem("token");// 如果有tokenif (token) {// 获取用户菜单信息,从store里面获取let userMenus = store.getters["getUserMenus"];// 如果没有用户菜单信息就获取用户菜单信息if (!userMenus) {userMenus = await store.dispatch("getUserMenuAction");// 菜单转成路由const userRoute = transformRoute(userMenus);// 动态添加路由 vue2 和 vue3 有细微差别// vue2// router.addRoutes(userRoute)// vue3// 因为 vue3 移除了 router.addRoutes()方法,所以需要手动实现addRoutes方法。addRoutes(userRoute);return next({ ...to });}// 有name说明路由存在,否则说明没有该路由if (to.name) {next();} else {// 去无权限页面next("/nopermission");}} else {// 否则去登录页next("/login");}} else {// 是白名单则直接进入next();}
});// 修改标题的工作可以放在全局后置守卫
router.afterEach((to, from) => {if (to.meta.title) {document.title = to.meta.title;}
});

我们再来看看 store 的逻辑

js
复制代码
import { createStore } from "vuex";export default createStore({state: {userMenus: null,},getters: {getUserMenus: (state) => state.userMenus,},mutations: {setUserMenus(state, payload) {state.userMenus = payload;},},actions: {async getUserMenuAction({ commit }) {// 模拟后端获取用户菜单信息apiconst getUserMenuApi = () => {// 假设只有about菜单return Promise.resolve([{path: "/about",name: "About",component: "../views/About.vue",title: "关于",},]);};const userMenus = await getUserMenuApi();commit("setUserMenus", userMenus);return userMenus;},},
});

使用

创建完路由后需要在 main.js 导入使用

js
复制代码
import router from "./router";// vue2写法
new Vue({router,render: (h) => h(App),
}).$mount("#app");// vue3写法
const app = createApp(App);
app.use(router).mount("#app");

在没登录的情况下,去aboutuserlist页面会重定向到登录页。

给本地添加token,模拟登录完成后,因为用户有about的菜单,所以去 about 页面是没问题的,去 userlist 页面则会重定向到没有权限页面。

总结

优点:

系统角色可以不固定,支持动态添加角色。适用于后台大型管理系统。

缺点:

实现相对复杂,而且需要后端配合的更多。

总结

第一种通过 beforeEach 实时监测用户权限的方式优势是实现简单,路由的权限在 meta 的 roles 里面配置。用户信息里面只需要包含当前用户的角色。缺点呢也很明显,系统所拥有的角色必须事先知道,然后以死代码的形式配置在 routes 里面,不支持动态添加角色。笔者觉得如果是做角色固定的系统是非常好的,比如什么图书管理系统、教师管理系统等。

第二种通过 通过 addRoutes 动态添加路由实现角色权限的方式优势是系统角色可以不固定,支持动态添加角色。很适用于后台大型管理系统,可以实时创建角色分配菜单。

当然、缺点就是实现起来比较复杂,需要后端一起参与设计。

相关文章:

企业级Vue路由角色权限应该怎么做?

角色权限 角色权限,简单来说就是登录的用户能看到系统的哪些页面,不能看到系统的哪些页面。一般是后台管理系统才会涉及到如此复杂的角色权限。 对于 vue 技术栈,实现角色权限一般有两种方式。 第一种是利用 beforeEach 全局前置守卫。 第…...

3.2.0 版本预告!Apache DolphinScheduler API 增强相关功能

Apache DolphinScheduler 3.2.0 版本即将发布,在此之前,为了让用户提前了解到大家所期待的新功能,我们制作了视频来”剧透“一些核心新发布。此前,我们比较全面地”剧透“的 3.2.0 版本的新功能,这次,我们来…...

测试工程师的工作

目录 1.何为软件测试工程师? 2.软件测试工程师的职责? 3.为什么要做软件测试? 4.软件测试的前途如何? 5.工具和思维谁更重要? 6.测试和开发相差大吗? 7.成为测试工程师的必备条件 8.测试的分类有哪…...

压力测试与测试工具jmeter的介绍

目录 一、性能指标 二、jmeter (一)JMeter 安装 (二)JMeter 压测示例 1、添加线程组 2、添加 HTTP 请求 3、添加监听器 4、启动压测&查看分析结果 (三)JMeter Address Already in use 错误解决 压力测…...

解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE)

解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE)结论分析 解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE) 解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE) ,java 二进制 最小值 减法 减1 结论 …...

【openpcdet】dbinfo内的信息

这就是kitti_dbinfos_train_sfd_seguv.pkl中【car】类别存储的信息。...

clickhouse查询缓存

为了实现最佳性能,数据库需要优化其内部数据存储和处理管道的每一步。但是数据库执行的最好的工作是根本没有完成的工作!缓存是一种特别流行的技术,它通过存储早期计算的结果或远程数据来避免不必要的工作,而访问这些数据的成本往…...

vue中使用Base64加密、解密以及des加密、解密

Base64加密、解密 第一步: npm install js-base64 --save 下载依赖 第二步: 直接引入即可 import { Base64 } from js-base64; 第三步: Base64.encode(xxxx) 其中 .encode() 加密 .decode() 解密 中间不需要使用加密的key等…...

关于丢失安卓秘钥的撞sha-1值的办法

实验得知,安卓sha-1和keytool生成秘钥签名文件的时间有关。 前提条件是,开发者必须知道生成秘钥的所有细节参数 以下是撞文件代码(重复生成) import time import osidx 0while True:cmdkeytool -keyalg RSA -genkeypair -alia…...

maven如何打包你会吗?

1.新建一个maven项目&#xff0c;在main/java中建立Main类 public class Main {public static void main(String[] args) {System.out.println("hello java ...");} } 2.添加依赖&#xff0c;使其成为可执行包 <build><plugins><!--打包成为可执行包-…...

idea 控制台 打印 Tomcat日志Tomcat Catalina Log控制台乱码问题

修改tomcat的日志配置文件 conf一>logging.properties 修改【1catalina.org.apache.juli.AsyncFileHandler.encoding】的值为gbk 1catalina.org.apache.juli.AsyncFileHandler.level FINE 1catalina.org.apache.juli.AsyncFileHandler.directory ${catalina.base}/logs 1…...

python我的世界

我的世界不知道大家有没有玩过&#xff0c;今天博主用python的Ursina库复刻了我的世界给大家分享 安装Ursina pip install ursina 导入Ursina from ursina import * from ursina.prefabs.first_person_controller import FirstPersonController 创建app app Ursina() 创建Voxe…...

SpringBoot+vue 大文件分片下载

学习链接 SpringBootvue文件上传&下载&预览&大文件分片上传&文件上传进度 Blob & File & FileReader & ArrayBuffer VueSpringBoot实现文件的分片下载 video标签学习 & xgplayer视频播放器分段播放mp4&#xff08;Range请求交互过程可以参…...

scanf函数读取数据 清空缓冲区

scanf函数读取数据&清空缓冲区 scanf 从输入缓冲区读取数据数据的接收数据存入缓冲区scanf 中%d读取数据scanf中%c读取数据 清空输入缓冲区例子用getchar()吸收回车练习 scanf 从输入缓冲区读取数据 首先&#xff0c;要清楚的是&#xff0c;scanf在读取数据的时候&#xff…...

js 文件常用转换

获取上传文件的arrayBuffer&#xff1a;var u8arr await file.arrayBuffer() 通过arrayBuffer转换成Buffer&#xff1a;Buffer.from(u8arr) 1. Blob、File → Base64 function fileToDataURL(file) {let reader new FileReader();reader.readAsDataURL(file);reader.onload…...

基于Open3D的点云处理15-特征点

Intrinsic shape signatures (ISS) 参考 ISS关键点: 基本原理是避免在沿主要方向表现出类似分布的点上检测关键点&#xff0c;在这些点上无法建立可重复的规范参考框架&#xff0c;因此后续描述阶段很难变得有效。在剩余点中&#xff0c;显着性由最小特征值的大小决定,以便仅包…...

算法刷题Day 58 每日温度+下一个更大元素I

Day 58 单调栈 739. 每日温度 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int> rst(temperatures.size());vector<int> decsStk; // 单调递减栈for (int i 0; i < temperatures.size(); i)…...

认识 spring AOP (面向切面编程) - springboot

前言 本篇介绍什么是spring AOP, AOP的优点&#xff0c;使用场景&#xff0c;spring AOP的组成&#xff0c;简单实现AOP 并 了解它的通知&#xff1b;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#xff01; 文章目录 前言1. 什么是s…...

将css文件中的px转化为rem

pxToRem.js /*** 使用方式&#xff1a;* 与引入的文件放在同一目录下进行引用配置&#xff0c;执行:node &#xff08;定义的文件&#xff09;*/ const fs require(fs) const path require(path) /*** entry&#xff1a;入口文件路径 type:Strng* pxtopx&#xff1a;以倍数转…...

JNI之Java实现远程打印

打印机是最常见的办公设备了。一般情况下如果需要实现打印&#xff0c;可通过前端print.js包来完成。但是&#xff0c;如果要实现智能办公打印&#xff0c;就可以使用JNI技术、封装接口、远程调用实现完成。 导包 jacob&#xff1a;Java COM Bridge <dependency><g…...

YOLOv5基础知识入门(2)— YOLOv5核心基础知识讲解

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOV4出现之后不久&#xff0c;YOLOv5横空出世。YOLOv5在YOLOv4算法的基础上做了进一步的改进&#xff0c;使检测性能得到更进一步的提升。YOLOv5算法作为目前工业界使用的最普遍的检测算法&#xff0c;存在着很多可以学习…...

免费的scrum敏捷开发管理工具

Scrum中非常强调公开、透明、直接有效的沟通&#xff0c;这也是“可视化的管理工具”在敏捷开发中如此重要的原因之一。通过“可视化的管理工具”让所有人直观的看到需求&#xff0c;故事&#xff0c;任务之间的流转状态&#xff0c;可以使团队成员更加快速适应敏捷开发流程。 …...

Hive创建外部表详细步骤

① 在hive中执行HDFS命令&#xff1a;创建/data目录 hive命令终端输入&#xff1a; hive> dfs -mkdir -p /data; 或者在linux命令终端输入&#xff1a; hdfs dfs -mkdir -p /data; ② 在hive中执行HDFS命令&#xff1a;上传/emp.txt至HDFS的data目录下&#xff0c;并命名为…...

leetcode 452. 用最少数量的箭引爆气球

2023.8.2 本题思路先将二维数组points按照第一个维度排序&#xff0c; 然后初始化射箭数为1&#xff0c;因为题中提示说了最少有一个气球。 在遍历这些气球&#xff0c;看是否有重叠&#xff0c;如果没有重叠区域&#xff0c;射箭数&#xff1b;如果有重叠区域&#xff0c;更新…...

Pytorch Tutorial【Chapter 3. Simple Neural Network】

Pytorch Tutorial【Chapter 3. Simple Neural Network】 文章目录 Pytorch Tutorial【Chapter 3. Simple Neural Network】Chapter 3. Simple Neural Network3.1 Train Neural Network Procedure训练神经网络流程3.2 Build Neural Network Procedure 搭建神经网络3.3 Use Loss …...

2.虚拟机开启kali_linux

首先你应该搞一个虚拟机&#xff0c;搞虚拟机可以看一下这个 附录三 虚拟机的使用_Suyuoa的博客-CSDN博客 然后你需要搞一个 kali linux的镜像 Get Kali | Kali Linux 镜像下载好之后解压&#xff0c;你会得到一个文件夹包含下面这些文件 之后打开VMware&#xff0c;点击打开虚…...

【StyleGAN2论文精读CVPR_2020】Analyzing and Improving the Image Quality of StyleGAN

【StyleGAN2论文精读CVPR_2020】Analyzing and Improving the Image Quality of StyleGAN 一、前言Abstract1. Introduction2. Removing normalization artifacts2.1. Generator architecture revisited2.2. Instance normalization revisited 3. Image quality and generator …...

医学图像处理

医学图像处理 opencv批量分片高像素图像病理图像色彩特征提取病理图像细微特征提取自动数据标注分类场景下的医学图像分析分割场景下的医学图像分析检测场景下的医学图像分析 , i ] k 8 < * I opencv批量分片高像素图像 医学图像通常是大像素&#xff08;1920x1080&…...

PyCharm安装使用2023年教程,PyCharm与现流行所有编辑器对比。

与PyCharm类似的功能和特性的集成开发环境&#xff08;IDE&#xff09;和代码编辑器有以下几种&#xff1a; Visual Studio Code&#xff08;VS Code&#xff09;&#xff1a;由Microsoft开发&#xff0c;VS Code是一个高度可定制和可扩展的代码编辑器。它支持多种编程语言&am…...

vue3中CompositionApi理解与使用

CompositionApi&#xff0c;组合式API&#xff0c;相当于react中hooks&#xff0c;函数式。 优势&#xff1a;1&#xff0c;增加了代码的复用性&#xff08;类似mixin&#xff0c;slot&#xff0c;高阶组件功能&#xff09; 2&#xff0c;代码可读性更好。可以将处理逻辑和视图…...