VUE项目中实现权限控制,菜单权限,按钮权限,接口权限,路由权限,操作权限,数据权限实现

VUE项目中实现权限控制,菜单权限,按钮权限,接口权限,路由权限,操作权限,数据权限实现

    • 权限系统分类(RBAC)
      • 引言
      • 菜单权限
      • 按钮权限
      • 接口权限
      • 路由权限
    • 菜单权限方案
      • 方案一:菜单与路由分离
      • 方案二:菜单和路由都由后端返回
    • 路由权限控制(如果后端设计菜单后返回的菜单都挂载到路由上)
      • 方案一:初始化即挂载全部路由
      • 方案二:按需挂载路由
    • 按钮权限方案
      • 方案一:使用 `v-if` 判断
      • 方案二:通过自定义指令进行按钮权限判断

权限系统分类(RBAC)

引言

在实际项目开发中,权限管理是一个关键功能,用于控制不同用户对系统资源的访问。权限是对特定资源的访问许可,权限控制的目的是确保用户只能访问到被分配的资源。例如,网站管理员可以对网站数据进行增删改查,而普通用户只能浏览

菜单权限

菜单管理涉及定义和管理应用中的导航菜单。不同的用户角色可能会看到不同的菜单项,从而访问不同的功能模块。

按钮权限

不同的用户角色可能享有不同的操作权限,例如管理员可以增删改查,而普通用户只能查看。

接口权限

接口权限通常采用 JWT 形式进行验证。如果请求未通过验证,服务器会返回 401 状态码,客户端则跳转到登录页面重新登录。登录成功后,客户端会拿到 token 并将其存储起来,通过 axios 请求拦截器在每次请求时携带 token。

路由权限

路由权限控制用户可以访问的页面和路径。

菜单权限方案

方案一:菜单与路由分离

前端组件:

{name: "login",path: "/login",component: () => import("@/pages/Login.vue")
}

全局路由卫生

function hasPermission(router, accessMenu) {if (whiteList.includes(router.path)) {return true;}const menu = Util.getMenuByName(router.name, accessMenu);return !!menu.name;
}Router.beforeEach(async (to, from, next) => {if (getToken()) {const userInfo = store.state.user.userInfo;if (!userInfo.name) {try {await store.dispatch("GetUserInfo"); // 获取用户信息await store.dispatch('updateAccessMenu'); // 更新访问菜单if (to.path === '/login') {next({ name: 'home_index' }); // 如果当前路径是登录页,跳转到首页} else {next({ ...to, replace: true }); // 替换当前路径}} catch (e) {if (whiteList.includes(to.path)) {next(); // 如果路径在白名单中,直接通过} else {next('/login'); // 否则跳转到登录页}}} else {if (to.path === '/login') {next({ name: 'home_index' }); // 如果当前路径是登录页,跳转到首页} else {if (hasPermission(to, store.getters.accessMenu)) {Util.toDefaultPage(store.getters.accessMenu, to, routes, next); // 跳转到默认页面} else {next({ path: '/403', replace: true }); // 没有权限,跳转到403页面}}}} else {if (whiteList.includes(to.path)) {next(); // 如果路径在白名单中,直接通过} else {next('/login'); // 否则跳转到登录页}}const menu = Util.getMenuByName(to.name, store.getters.accessMenu);Util.title(menu.title); // 设置页面标题
});Router.afterEach((to) => {window.scrollTo(0, 0); // 滚动条回到顶部
});

优点:
前后端职责分明,前端负责路由定义,后端负责菜单管理。

缺点:
需要维护菜单与路由的对应关系,增加了复杂性。
每次路由跳转都需要进行权限判断

不推荐!!!!!

方案二:菜单和路由都由后端返回

思路: 由后端设计菜单表进行菜单管理,返回给前端后,由前端进行拼接成路由,然后进行挂载到全局路由上,router.addRouter()方法上。进行加载,
在这里插入图片描述
后端返回菜单json格式

[{name: "home",path: "/",component: "home"},{name: "userinfo",path: "/userinfo",component: "userInfo"}
]

前端处理逻辑

// 将后端菜单数据转换为路由格式
function generateAsyncRouter(menus) {const asyncRoutes = menus.map(menu => {const route = {path: menu.path,name: menu.menuName,meta: {title: menu.menuName,icon: menu.icon},hidden: menu.hidden}// 处理组件if (menu.menuType === 'content') {// 目录类型route.alwaysShow = trueroute.component = Layoutif (menu.children && menu.children.length > 0) {route.children = generateAsyncRouter(menu.children)}} else if (menu.menuType === 'menu') {// 菜单类型,动态加载组件route.component = loadView(menu.path)}// button类型的不需要生成路由return route})// 添加404页面路由asyncRoutes.push({ path: '*', redirect: '/404', hidden: true })

优点:
前后端高度集成,灵活性高。

缺点:
前后端配合要求更高。
每次路由跳转都需要进行权限判断。
推荐这种用法

路由权限控制(如果后端设计菜单后返回的菜单都挂载到路由上)

方案一:初始化即挂载全部路由

const routerMap = [{path: '/permission',component: Layout,redirect: '/permission/index',alwaysShow: true,meta: {title: '权限管理',icon: 'lock',roles: ['admin', 'editor'] // 标记权限},children: [{path: 'page',component: () => import('@/views/permission/page'),name: 'pagePermission',meta: {title: '页面权限',roles: ['admin'] // 标记权限}},{path: 'directive',component: () => import('@/views/permission/directive'),name: 'directivePermission',meta: {title: '指令权限'// 如果没有设置权限标识,意味着这个页面不需要权限}}]}
];

方案二:按需挂载路由

import router from './router';
import store from './store';
import { Message } from 'element-ui';
import NProgress from 'nprogress'; // 进度条
import 'nprogress/nprogress.css'; // 进度条样式
import { getToken } from '@/utils/auth'; // 从 cookie 获取 tokenNProgress.configure({ showSpinner: false }); // 配置进度条function hasPermission(roles, permissionRoles) {if (roles.includes('admin')) return true; // 管理员权限直接通过if (!permissionRoles) return true;return roles.some(role => permissionRoles.includes(role));
}const whiteList = ['/login', '/authredirect']; // 不需要重定向的白名单router.beforeEach((to, from, next) => {NProgress.start(); // 开始进度条if (getToken()) { // 确定是否有 tokenif (to.path === '/login') {next({ path: '/' });NProgress.done(); // 如果当前页面是仪表盘,不会触发 afterEach 钩子,所以手动处理} else {if (store.getters.roles.length === 0) { // 用户信息store.dispatch('GetUserInfo').then(res => { // 获取用户信息const roles = res.data.roles; // 注意:角色必须是一个数组!例如:['editor','develop']store.dispatch('GenerateRoutes', { roles }).then(() => { // 生成路由router.addRoutes(store.getters.addRouters); // 添加路由next({ ...to, replace: true }); // 替换当前路径,防止留下历史记录});}).catch((err) => {store.dispatch('FedLogOut').then(() => {Message.error(err || '验证失败,请重新登录');next({ path: '/' });});});} else {if (hasPermission(store.getters.roles, to.meta.roles)) {next(); // 有权限,继续跳转} else {next({ path: '/401', replace: true, query: { noGoBack: true }}); // 没有权限,跳转到401页面}}}} else {if (whiteList.includes(to.path)) {next(); // 如果路径在白名单中,直接通过} else {next('/login'); // 否则跳转到登录页NProgress.done(); // 如果当前页面是登录页,不会触发 afterEach 钩子,所以手动处理}}
});router.afterEach(() => {NProgress.done(); // 结束进度条
});

这种是我实现的方式
全局路由上,获取到全部菜单,前端进行路由加载
在这里插入图片描述

按钮权限方案

方案一:使用 v-if 判断

优点:

简单直观,易于实现。
缺点:

如果页面较多,每个页面都需要获取用户权限并进行判断,增加复杂性。

方案二:通过自定义指令进行按钮权限判断

自定义指令:

import permissionV from './permission-v';const install = function(Vue) {Vue.directive('permission-v', permissionV)
}if (window.Vue) {window['permission-v'] = permissionVVue.use(install); // eslint-disable-line
}permissionV.install = install
export default permissionV

permission-v.js

import store from '@/store'function checkBtnPermission(el, binding) {const { value } = bindingconst permissions = store.getters && store.getters.userInfo.permissionsif (value && value instanceof Array) {if (value.length > 0) {const permission = valueconst hasPermission = permissions.some(permiss => {return permission.includes(permiss)})if (!hasPermission) {el.parentNode && el.parentNode.removeChild(el)}}} else {throw new Error(`need permissions! Like v-permission="['admin','editor']"`)}
}export default {inserted(el, binding) {checkBtnPermission(el, binding)},update(el, binding) {checkBtnPermission(el, binding)}
}

注册到全局

import permission from '@/directive/permission-v'
// 注册全局指令
Vue.use(permission)
Vue.directive('permission-v', permission)//使用方式 v-permission-v
<el-button v-permission-v="['system:role:add']" type="primary" @click="handleAdd" icon="el-icon-plus">新增角色</el-button>

感兴趣的同学可以关注下,日常更新技术文章和demo示例免费的。
在这里插入图片描述

https://bytecodestudio.site/

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15901.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pdf手册阅读(1)--数字签名篇

原文阅读摘要 PDF支持的数字签名&#xff0c; 不仅仅是公私钥签名&#xff0c;还可以是指纹、手写、虹膜等生物识别签名。PDF签名的计算方式&#xff0c;可以基于字节范围进行计算&#xff0c;也可以基于Pdf 对象&#xff08;pdf object&#xff09;进行计算。 PDF文件可能包…

CSS3+动画

浏览器内核以及其前缀 css标准中各个属性都要经历从草案到推荐的过程&#xff0c;css3中的属性进展都不一样&#xff0c;浏览器厂商在标准尚未明确的情况下提前支持会有风险&#xff0c;浏览器厂商对新属性的支持情况也不同&#xff0c;所有会加厂商前缀加以区分。如果某个属性…

微信小程序分包异步化

分包1引入分包2的组件或者js 引入组件&#xff1a; 主包里的pages/tabbars/tabbar1/tabbar1页面 引入分包sub1的sub1/components/sub1-component/sub1-component组件 1、分包预下载 首先在app.js定义preloadRule "preloadRule": {"pages/tabbars/tabbar1/tabb…

后端java工程师经验之谈,工作7年,mysql使用心得

mysql 工作7年&#xff0c;mysql使用心得 mysql1.创建变量2.创建存储过程2.1&#xff1a;WHILE循环2.2&#xff1a;repeat循环2.3&#xff1a;loop循环2.4&#xff1a;存储过程&#xff0c;游标2.5&#xff1a;存储过程&#xff0c;有输入参数和输出参数 3.三种注释写法4.case …

基于 GEE 利用插值方法填补缺失影像

目录 1 完整代码 2 运行结果 利用GEE合成NDVI时&#xff0c;如果研究区较大&#xff0c;一个月的影像覆盖不了整个研究区&#xff0c;就会有缺失的地方&#xff0c;还有就是去云之后&#xff0c;有云量的地区变成空值。 所以今天来用一种插值的方法来填补缺失的影像&#xf…

unity学习34:角色相关3,触发器trigger,铰链 hingejoint 等 spring joint, fixed joint

目录 1 触发的实现条件 1.1 碰撞的的实现条件 1.2 触发的实现条件 1.3 触发器trigger&#xff0c;直接拿 碰撞器collider修改下配置即可 2 触发器相关实验&#xff1a;触发开门效果 2.0 目标 2.1 player物体的属性 2.2 新建一个trigger 物体 2.3 新建一个被trigger 控…

(1/100)每日小游戏平台系列

每日小游戏平台 项目简介以及地址 准备开发一个一百天小游戏平台&#xff0c;使用Flask构建的简单游戏导航网站&#xff0c;无需登录&#xff0c;让大家在返工的同时也可以愉快的摸鱼玩耍。 每天更新一个小游戏上传&#xff0c;看看能不能坚持一百天。 这些小游戏主要使用前端…

从零到一:基于Rook构建云原生Ceph存储的全面指南(上)

文章目录 一.Rook简介二.Rook与Ceph架构2.1 Rook结构体系2.2 Rook包含组件1&#xff09;Rook Operator2&#xff09;Rook Discover3&#xff09;Rook Agent 2.3 Rook与kubernetes结合的架构图如下2.4 ceph特点2.5 ceph架构2.6 ceph组件 三.Rook部署Ceph集群3.1 部署条件3.3 获取…

第40天:Web开发-JS应用VueJS框架Vite构建启动打包渲染XSS源码泄露代码审计

#知识点 1、安全开发-VueJS-搭建启动&打包安全 2、安全开发-VueJS-源码泄漏&代码审计 一、Vue搭建创建项目启动项目 1、Vue 框架搭建->基于nodejs搭建&#xff0c;安装nodejs即可 参考&#xff1a;https://cn.vuejs.org/ 已安装18.3或更高版本的Node.js 2、Vue 创建…

DeepSeek做赛车游戏

赛车模型 2D生成图片 任意AI图片软件SD&#xff0c;MJ 图片生成3D模型 车身 车轮 场景 Rodin,Tripo和Meshy 询问deepSeek如何开发 拷贝代码 将汽车运行代码拖到汽车上 再让AI写个摄像头跟随代码 再去提问deepseek控制轮胎和一些处理细节

软考高级《系统架构设计师》知识点(一)

计算机硬件 校验码 码距&#xff1a;就单个编码A:00而言&#xff0c;其码距为1&#xff0c;因为其只需要改变一位就变成另一个编码。在两个编码中&#xff0c;从A码到B码转换所需要改变的位数称为码距&#xff0c;如A:00要转换为B:11&#xff0c;码距为2。一般来说&#xff0c;…

亚博microros小车-原生ubuntu支持系列:26手势控制小车基础运动

背景知识 手指检测&#xff1a;亚博microros小车-原生ubuntu支持系列&#xff1a;4-手部检测-CSDN博客 程序功能说明 功能开启后&#xff0c;摄像头捕获图像&#xff0c;识别手势来控制小车移动。 手势 “5”小车前进拳头小车后退手势 “1”小车向左手势 “2”小车向右 运…

OpenFeign远程调用返回的是List<T>类型的数据

在使用 OpenFeign 进行远程调用时&#xff0c;如果接口返回的是 List 类型的数据&#xff0c;可以通过以下方式处理&#xff1a; 直接定义返回类型为List Feign 默认支持 JSON 序列化/反序列化&#xff0c;如果服务端返回的是 List的JSON格式数据&#xff0c;可以直接在 Feig…

【hive】记一次hiveserver内存溢出排查,线程池未正确关闭导致

一、使用 MemoryAnalyzer软件打开hprof文件 很大有30G&#xff0c;win内存24GB&#xff0c;不用担心可以打开&#xff0c;ma软件能够生成索引文件&#xff0c;逐块分析内存&#xff0c;如下图。 大约需要4小时。 overview中开不到具体信息。 二、使用Leak Suspects功能继续…

【Docker】

一、概述 1、Docker为什么出现&#xff1f; 开发和运维两套环境&#xff0c;而环境配置十分麻烦。如在Windows上开发&#xff0c;要发布到Linux上运行。 Docker给以上问题提出解决方案&#xff1a;Java --- Jar(环境&#xff09;---打包项目带上环境&#xff08;镜像&#x…

游戏手柄Type-c方案,支持一边充电一边传输数据

乐得瑞推出LDR6023SS&#xff0c;专门针对USB-C接口手机手柄方案&#xff0c;支持手机快充&#xff0c;支持任天堂游戏机&#xff0c;PS4等设备~同时支持手机充电跟数据传输 1、概述 LDR6023SS SSOP16 是乐得瑞科技针对 USB Type-C 标准中的 Bridge 设备而开发的双 USB-C DRP …

【报错解决】Sql server 2022连接数据库时显示证书链是由不受信任的颁发机构颁发的

SSMS 20在连接Sql server 2022数据库时有如下报错&#xff1a; A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - 证书链是由不受信任的颁发机构颁发的。 原因是尝试使…

「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

NineData云原生智能数据管理平台新功能发布|2025年1月版

本月发布 14 项更新&#xff0c;其中重点发布 6 项、功能优化 7 项、安全性更新 1 项。 重点发布 数据库 Devops - 数据导出功能增强 支持 AWS ElastiCache 数据源&#xff1a;现已支持通过 SQL 查询语句或直接通过库表导出 AWS ElastiCache 数据&#xff0c;方便用户快速提取…

游戏引擎学习第96天

讨论了优化和速度问题&#xff0c;以便简化调试过程 节目以一个有趣的类比开始&#xff0c;提到就像某些高端餐厅那样&#xff0c;菜单上充满了听起来陌生或不太清楚的描述&#xff0c;需要依靠服务员进一步解释。虽然这听起来有些奇怪&#xff0c;但实际上&#xff0c;它反映…