RBAC权限管理(详细)

article/2025/9/16 9:13:25

RBAC权限设计思想

为了达成不同账号(员工、总裁)登录系统后看到不同页面,执行不同功能,RBAC(Role-Based Access control)权限模型,就是根据角色的权限,分配可视页面。

三个关键点:

用户:使用系统的人
角色:使用系统的人是什么职位(员工、经理、总裁)
权限点:职位可以做的事情(左侧菜单栏中的功能模块——>增删改查)
在这里插入图片描述
测试流程
①在员工管理页新增员工这是三要素中的用户
②为新增的员工分配角色
③在公司设置里为角色分配权限

💢系统中的权限不能随意添加,必须是以开发出来的权限(左侧菜单栏里可实现的页面)
💢用户和角色之间是一对多的关系,一个人身兼数职。

具体实现

1.实现分配角色
点击分配角色、弹出框,框里含有已有角色列表,点击分配角色时将id传过去,根据id显示当前用户已有的角色。

分配角色父组件src/employees/employee.vue

<template slot-scope="scope"><el-button type="text" size="smell" @click="assignFn(scope.row)">分配角色</el-button></template><el-dialogtitle="分配角色":visible.sync="showDialogRole":close-on-press-escape="false":close-on-click-modal="false"@close="showDialogRole=false"><assign-role :id="curId" ref="assignRole" @close="showDialogRole=false" /></el-dialog>//import 导入复原框子组件// -------------------------------------------分配角色----------------------------------assignFn(row) {this.showDialogRole = truethis.curId = row.idthis.$nextTick(() => {this.$refs.assignRole.getRoleListFn()})}

分配角色的子组件:employees/assignRole.vue

<template><div><el-checkbox-group v-model="rolesList"><el-checkbox v-for="item in checkList" :key="item.id" :label="item.id">{{ item.name }}</el-checkbox></el-checkbox-group><div style="margin-top: 20px; text-align: right"><el-button type="primary" @click="submitFn">确定</el-button><el-button @click="closeDialog">取消</el-button></div></div>
</template>
<script>
import { getAllRoleAPI } from '@/api/settings'
import { getDetailInfo } from '@/api/user.js'
import { assignRolesAPI } from '@/api/employees.js'
export default {name: 'AssignRole',props: {id: { type: String,	required: true }},data() {return {checkList: [], // 角色列表rolesList: []// 用户已有角色}},created() {},methods: {// ------------------------------------提交角色-----------------------------------async  submitFn() {const resp = await assignRolesAPI({ id: this.id, roleIds: this.rolesList })console.log(resp)this.$emit('close')},// ----------------------------------获取角色列表----------------------------------async  getRoleListFn() {const resp = await getAllRoleAPI({ page: 1, pagesize: 100 })console.log(resp)this.checkList = resp.data.rowsconst res = await getDetailInfo(this.id)console.log(res)this.rolesList = res.data.roleIds},// -------------------------------------取消按钮------------------------------------closeDialog() {this.$emit('close')}}
}
</script>

💢《el-checkbox-group v-model=“rolesList”》中v-model绑定的值是数组表示可多选。
💢在模板中渲染数据时

{{ item.name }}
其中label决定当前选中的值,{{要展示的角色名称}}

2.实现分配权限

父组件中(views/setings/setings.vue):准备弹框 -> 注册事件 -> 提供数据方法

<template><div class="settings-container"><div class="app-container"><el-card><!-- 具体页面结构 --><el-tabs><!-- 放置页签 --><el-tab-pane label="角色管理"><!-- 表格 --><el-table :data="tableList"><el-table-column label="操作"><!-- scope只是插槽占位置的名字而已,重要的是里面的.row这是每一行的对象,是固定写法 --><template slot-scope="scope"><el-button size="small" type="success" @click="hAssign(scope.row.id)">分配权限</el-button></template></el-table-column></el-table><el-row type="flex" justify="center" align="middle" style="height: 60px"></el-row></el-tab-pane></el-tabs></el-card><!-- 分配权限的弹层 --><el-dialogtitle="分配权限(一级为路由页面查看权限-二级为按钮操作权限)":visible.sync="showDialogAssign"><assign-permission ref="assignPermission" :role-id="roleId" @close="showDialogAssign=false" /></el-dialog></div></div>
</template>
<script>
export default {name: 'Setting',components: {assignPermission},data() {return {showDialogAssign: false, // 分配权限对话框methods: {// -----------------------------------------分配权限-------------------------------------hAssign(id) {this.roleId = idthis.showDialogAssign = truethis.$nextTick(() => {this.$refs.assignPermission.getRoleDetail()})}}
}
</script>

子组件中(settings/assignPermission.vue):

<template><div><!-- 权限点数据展示:check-strictly  设置true,可以关闭父子关联 --><el-treeref="tree":data="permissionData":props="{ label: 'name' }"node-key="id"default-expand-all:show-checkbox="true":check-strictly="true"/><div style="text-align:right;"><el-button @click="hCancel">取消</el-button><el-button type="primary" @click="getAssignRoleFn">确定</el-button></div></div>
</template><script>
import { getPermissionListAPI } from '@/api/permissions.js'
import { tranListToTreeData } from '@/utils/index.js'
import { getRoleDetail, getAssignRoleAPI } from '@/api/settings.js'
export default {props: {roleId: {type: String,required: true}},data() {return {permissionData: [] // 存储权限数据}},created() {this.getPermissionListFn()},methods: {// -------------------------------------------获取权限列表-------------------------------------async  getPermissionListFn() {const resp = await getPermissionListAPI()console.log(resp)this.permissionData = tranListToTreeData(resp.data)console.log('数组转树', this.permissionData)},// --------------------------------------------获取角色详情------------------------------------async  getRoleDetail() {const resp = await getRoleDetail(this.roleId)console.log(resp)// 回填到树上this.$refs.tree.setCheckedKeys(resp.data.permIds)},// ---------------------------------------------关闭弹层------------------------------------------hCancel() {// 通过父组件去关闭弹层this.$emit('close')// 下次根据id获取角色权限数组时,将容器清空,以免影响下次保存this.$refs.tree.setCheckedKeys([])},// ------------------------------------------给角色分配权限--------------------------------------async getAssignRoleFn() {const pid = this.$refs.tree.getCheckedKeys()const resp = await getAssignRoleAPI({ id: this.roleId, permIds: pid })console.log(resp)this.hCancel()// 通知父组件关闭弹层this.$message.success('分配成功')}}
}
</script><style></style>

3.页面权限控制

1. 左侧菜单权限控制(不同的用户进来系统之后,看到的菜单是不同的)2. 操作按钮权限控制 (页面上的按钮,不同的人也有不同权限)3. 权限数据所在位置:下图是管理员登录时,可以看到的权限。![在这里插入图片描述](https://img-blog.csdnimg.cn/5bb6a3a086d6498c911224f19bc2840e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5YuH5pWi54mb54mb77yM5Yay5Yay5Yay,size_11,color_FFFFFF,t_70,g_se,x_16)3.1修改权限数据

只有管理员才可修改权限数据,所以要先新增用户——>分配角色——>分配权限、重新等新用户账号观察权限数据(data.roles.menus,
points)

3.2 动态生成左侧菜单
新用户登录成功页面跳转、进入导航守卫
在这里插入图片描述
3.3 在router/index.js中的路由配置中删除动态路由的部分改为:routes: […constantRoutes]
3.4 在permission.js中引入动态路由,并使用addRoutes动态添加,此时左侧动态路由只剩下静态首页了,可在地址栏输入地址实现跳转(addRoutes的作用)
3.5 从actions中返回菜单项

  async getUserInfo(context) {// 1. ajax获取基本信息,包含用户idconst rs = await getUserInfoApi()console.log('用来获取用户信息的,', rs)// 2. 根据用户id(rs.data.userId)再发请求,获取详情(包含头像)const info = await getUserDetailById(rs.data.userId)console.log('获取详情', info.data)// 把上边获取的两份合并在一起,保存到vuex中context.commit('setUserInfo', { ...info.data, ...rs.data })// 当前用户可以看到的菜单 res.data.roles.menus
+     return rs.data.roles.menus},

3.6 在permission.js中获取action的返回值并过滤

/ 引入所有的动态路由表(未经过筛选)
+ import router, { asyncRoutes } from '@/router'const whiteList = ['/login', '/404']
router.beforeEach(async(to, from, next) => {// 开启进度条NProgress.start()// 获取本地token 全局getterconst token = store.getters.tokenif (token) {// 有tokenif (to.path === '/login') {next('/')} else {if (!store.getters.userId) {
+        const menus = await store.dispatch('user/getUserInfo')//根据权限过滤动态数组
+        const filterRoutes = asyncRoutes.filter(route => {
+        const routeName = route.children[0].name
+        return menus.includes(routeName)
+       })// 1.改写成动态添加的方式
+       router.addRoutes(filterRoutes)//2. 生成左侧菜单时,也应该去vuex中拿
+       store.commit('menu/setMenuList', filterRoutes)
+       //3.解决刷新时出现的白屏bugnext({ ...to, // 保证路由添加完了再进入页面(可理解为重新进一次)replace: true// 重新进一次,不保留重复历史})}else{next()}} else {// 没有tokenif (whiteList.includes(to.path)) {next()} else {next('/login')}}// 结束进度条NProgress.done()
})
 💢当前的菜单(src\layout\components\Sidebar\index.vue)使用的数据:this.$router.options.routes **可以拿到当前路由配置,设置的路由表数据**但是这个数据是固定的,所以将此数据换为 this.$router.options.routes就可以动态拿到路由表的数据。

💢如果想调用addRoutes方法之后,路由表数据立刻在左侧菜单栏中显示,那就将动态路由菜单保存在vuex中

3.7修复bug
3.7.1解决刷新出现的白屏(路由守卫中的 //3…)
3.7.2退出后,再次登陆,发现菜单异常 (控制台有输出说路由重复)
在这里插入图片描述
原因:路由设置是通过router.addRoutes(filterRoutes)来添加的,退出时,并没有清空,再次登陆,又加了一次,所以有重复。
需要将路由权限重置 (恢复默认) 将来登录后再次追加才可以,不然的话,就会重复添加
解决:
router/index.js文件,有一个重置路由方法

// 重置路由
export function resetRouter() {const newRouter = createRouter()router.matcher = newRouter.matcher // 重新设置路由的可匹配路径
}

在登出的时候, 调用一下即可store/modules/user.js

import { resetRouter } from '@/router'
// 退出的action操作
logout(context) {// 1. 移除vuex个人信息context.commit('removeUserInfo')// 2. 移除token信息context.commit('removeToken')// 3. 重置路由+ resetRouter()
}

4.按钮级控制

4.1 自定义指令:自己定义的指令,因为本身指令不够用,所以我们需要自已去定义。

4.2 解决按钮级别的权限验证 ——在main.js中,定义全局指令

// 注册一个全局自定义指令 `v-allow`
Vue.directive('allow', {inserted: function(el, binding) {// 从vuex中取出points,const points = store.state.user.userInfo.roles.points// 如果points有binding.value则显示if (points.includes(binding.value)) {// console.log('判断这个元素是否会显示', el, binding.value)} else {// el.style.display = 'none',这个只是隐藏了,懂业务的通过检查还可以显示,所以要销毁el.parentNode.removeChild(el)}}
})

使用

<el-button
+           v-allow="'import_employee'"type="warning"size="small"@click="$router.push('/import')">导入excel</el-button>

※这里的:'import_employee’是从标识符来的
在这里插入图片描述


http://chatgpt.dhexx.cn/article/Tgv8cn4n.shtml

相关文章

什么是RBAC

一、RBAC是什么 1、RBAC模型概述 RBAC模型&#xff08;Role-Based Access Control&#xff1a;基于角色的访问控制&#xff09;模型是20世纪90年代研究出来的一种新模型&#xff0c;但其实在20世纪70年代的多用户计算时期&#xff0c;这种思想就已经被提出来&#xff0c;直到…

最小生成树,秒懂!

&#x1f447;&#x1f447;关注后回复 “进群” &#xff0c;拉你进程序员交流群&#x1f447;&#x1f447; 作者丨bigsai 来源丨bigsai 前言 在数据结构与算法的图论中&#xff0c;(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法。但是可能很多人对概念不是…

算法 - 最小生成树实现

算法能力是一个门槛&#xff0c;也是个有基础的门槛 无论你是iOS工程师&#xff0c;android工程师&#xff0c;java工程师&#xff0c;前端&#xff0c;后端还是全栈等等… 算法能力的强弱一方面在于思想&#xff0c;你是否有计算机思维抽象具体问题的能力 更重要的还在与基…

最小树形图(有向图的最小生成树)

我们知道&#xff0c;无向图的最小生成树的求法有Krusal和prime算法&#xff0c;一个是归点一个是归边&#xff0c;在具体实现上Krusal可以用并查集实现&#xff0c;难度不大。 这里稍微区别一下最短路径和最小生成树&#xff08;因为我又搞混了23333&#xff09; 最小生成树能…

Kruskal算法(最小生成树)

上篇Prim算法简要的讲解了最小生成树。也提到过Prim算法堆优化&#xff0c;但本蒟蒻并没有贴Prim &#xff08;堆优化的代码&#xff09;。至于为什么没有贴呢&#xff1f;上篇Prim算法blog末尾有说明。 好勒&#xff01;咱们接着讲Kruskal算法。这跟Prim算法有很大的…

最小生成树matlab求解

一、最小生成树 连通所有顶点且总路径最小修建连通7个城市的铁路网&#xff0c;可修建的路线和对应造价如图所示&#xff0c;如何修建使总费用最少&#xff1f; 问题分析&#xff1a; 连通7个城市&#xff1a;生成的图中&#xff0c;从任意顶点起步&#xff0c;沿着边一定可以…

最小生成树——贪心算法

文章目录 1.生成树和最小生成树1.1 问题的定义1.2 MST性质 2.普里姆算法&#xff08;Prim&#xff09;2.1 算法流程2.2 算法正确性证明2.3 算法实现2.4 时间复杂度2.5 测试代码 3.克鲁斯卡尔算法&#xff08;kruskal&#xff09;3.1 算法流程3.2 算法正确性证明3.3 算法实现 参…

C++ 最小生成树

目录&#xff1a; 前置知识 最小生成树 Prim 算法 kruskal 算法 前置知识&#xff1a; 连通图&#xff1a;在无向图中&#xff0c;若任意两个顶点 u 与 v 都有路径相通&#xff0c;则称该无向图为连通图。 强连通图&#xff1a;在有向图中&#xff0c;若任意两个顶点 u 与 …

最小生成树(C语言实现)

求这个网的最小生成树 /** 普里姆算法和克鲁斯卡尔算法求最小生成树* 采用邻接矩阵存储**/ #include<stdio.h>#define MAX_VERTEX_NUM 20 //图的定义 typedef struct {int vertexNum;int edgeNum;char vertex[MAX_VERTEX_NUM];int arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]…

最小生成树(C语言)

最小生成树问题&#xff08;C语言&#xff09; 所谓一个 带权图 的最小生成树&#xff0c;就是原图中边的权值最小的生成树 &#xff0c;所谓最小是指边的权值之和小于或者等于其它生成树的边的权值之和。 kruskal 克鲁斯卡尔算法&#xff08;Kruskal&#xff09;是一种使用贪…

最小生成树kruskal算法

最小生成树kruskal算法 概述算法分析代码 概述 克鲁斯卡尔 ( K r u s k a l ) (Kruskal) (Kruskal)算法是求连通网的最小生成树的另一种方法。与普里姆 ( P r i m ) (Prim) (Prim)算法不同&#xff0c;它的时间复杂度为 O ( e l o g e ) O(eloge) O(eloge)(e为网中的边数)&…

最小生成树:

定义&#xff1a; 将图中的 n 结点用 n-1 条边连接起来&#xff0c;使其各个边的权值之和最小的生成树。 普里姆算法&#xff1a; 从点的角度出发。 1、start 数组的值表示起始点的下标&#xff0c;start 的下标代表目的顶点&#xff1b;lowcost 数组的下标代表目的顶点&…

图——最小生成树

图——最小生成树 1. 基本概念 在一个连通无向图G(V, E)中&#xff0c;对于其中的每条边(u,v)∈E&#xff0c;赋予其权重w(u, v)&#xff0c;则最小生成树问题就是要在G中找到一个连通图G中所有顶点的无环子集T⊆E&#xff0c;使得这个子集中所有边的权重之和w(T) ∑ ( u , …

最小生成树的Kruskal算法-详解

最小生成树的Kruskal算法 一、 什么是最小生成树 1.1 最小生成树定义&#xff1a; 一个有 n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n 个结点&#xff0c;并且有保持图连通的最少的边。最小生成树可以用kruskal&#xff08;克鲁斯卡尔&a…

最小生成树(C语言简单实现)

最小生成树 本文参考自《大话数据结构》 一个连通图的生成树是一个极小的连通子图&#xff0c;它含有图中全部的顶点&#xff0c;但只有足以构成一棵树的n-1条边。我们把构造连通网的最小代价生成树称为最小生成树 。 找连通网的最小生成树&#xff0c;经典的有两种算法&#…

最小生成树怎么画?

介绍最小生成树的图形画法~以下图为例&#xff1a; 1、从1开始&#xff0c;以1为顶点画圈。在红色线经过的部分中&#xff0c;可见权重分别为6、1、5&#xff0c;最小权重为1。如下图。 2、以上图中得到的1、3为顶点的图中&#xff0c;继续画线&#xff0c;图为黄色线部分。经过…

最小生成树算法

最小生成树算法 生成树的概念最小生成树算法Prim算法Kruskal算法 生成树的概念 若图是连通的无向图或强连通的有向图&#xff0c;则从其中任一顶点出发&#xff0c;调用一次 d f s dfs dfs或者 b f s bfs bfs后&#xff0c;可以系统的访问图中所有顶点。若图是有根的有向图 &a…

【图】最小生成树

最小生成树&#xff1a;构造连通网的最小代价生成树。 最小生成树有两种算法&#xff1a;普利姆算法、克鲁斯卡尔算法。 普利姆&#xff08;Prim&#xff09;算法 加点&#xff0c;选择相邻点中边权最小的 需要两个一维数组&#xff0c;一个存权值&#xff0c;另一个存起始点…

最小生成树-Kruskal算法

数据结构:最小生成树-Kruskal算法 什么是最小生成树&#xff0c;最小生成树就是求图中把所有点都访问到的最短路径的长度 Kruskal算法采用的是边贪心思想&#xff0c;我们先大概讲一下它的大概思想&#xff0c;首先我们先假设先隐藏所有的边&#xff0c;这样每个点会成为一个连…

最小生成树(kruskal算法)

一、概述 最小生成树问题顾名思义&#xff0c;概括来说就是路修的最短。 接下来引入几个一看就明白的定义&#xff1a; 最小生成树相关概念&#xff1a; 带权图&#xff1a;边赋以权值的图称为网或带权图&#xff0c;带权图的生成树也是带权的&#xff0c;生成树T各边的权值…