说到角色管理就离不开权限管理,这里我们简单说一下权限管理。权限管理简单来说就是控制当前系统用户可以使用哪些功能,具体到模块、按钮等。一个用户可能拥有多个角色,一个角色对应多个页面的权限、界面的权限。角色管理往往是根据业务管理需要预先在系统中设定的固定标签,每个角色对应一个明确的系统权限,它是一个集合的概念,由很多个最小权限颗粒组成。我们把权限赋给这个角色,再赋给账户,从而实现账户的权限分配。角色管理起到桥梁的作用,引入角色的概念,可以帮助我们灵活扩展,让一个账户可以拥有多个角色。角色所拥有的系统权限一般不会随意改变,也不会随着用户的增减而改变,相比于用户管理来说更加稳定。
商业原因
随着公司业务的发展,规模越来越大,越来越复杂,角色权限起着至关重要的作用。以现在的公司为例:不同的角色拥有不同的权限。
公司领导:超级管理员(分配角色权限)掌控整个业务结构和权限
程序员(前端):开发权限,发布前审批,Leader审核后有权发布上线代码。
程序员(后端):开发权限、发布权限、数据库操作权限(开发、测试服务器)。正式服务器需要leader审核通过后才能发布。
测试:发布权限,数据库操作权限(开发测试服务器),无官方服务器操作权限
产品:管控产品、配置产品后台、分配操作权限
Operations:操作配置项(商品、商品上架及下架状态、奖品后台配置、库存管控)
数据(BI)部门:数据监测与统计权威
好的角色权限设计可以让每个人各司其职,做好自己的事情,避免线上环境出现大的问题(因为开发修改操作配置项,修改系统崩溃)
因此角色管理设计是至关重要的环节。
常见的RBAC3原则及前端实现
RBAC3整合了RBAC0、RBAC1、RBAC2模型,是RBAC权限管理模型的顶峰。
RBAC0
有时候不一定是权限表,可能是十进制整数,需要转为二进制按照后端约定确定权限。
RBAC1 RBAC2 设计表结构和逻辑页访问权限,两种方式的数据权限设计
首先我们先看一下流程
用户 => 多角色 => 菜单
=> 资源
=> ................
从这里我们可以看出来
用户 > 可拥有多个角色 > 一个角色可拥有多个其他权限 (菜单,资源接口 ,其他... )
最后 这个用户 拥有的就是 多个角色权限 合并之后的整体权限
从流程看 我们要先进行 例如 菜单列表( 有哪些菜单) 资源列表( 有哪些接口)等 的管理界面编写
下一步 把角色需要的 菜单或资源勾选上 这些权限赋给 角色
最后 把我们定义好的角色( 例如管理员,超级管理员,访客) 赋给 用户
最常见的方式是分配三个角色:超级管理员、管理员、操作员。在开发过程中:
一般情况下,通过路由权限的划分来控制账户可见、可用的路由;
通过增加、删除、修改、查看模块接口的权限划分,可以控制账户对接口的调用权限;
需要对不同权限的角色进行管控:访问的页面权限不同,没有权限的页面无法访问;不同角色的功能权限不同;没有对应的资源权限则无法进行操作。
前端根据后端提供的menuList和resourceList
不同权限的角色注册不同的页面路由,不同权限的角色展示不同的功能操作。
前端根据数据库中的菜单结构和权限信息进行菜单渲染,只显示自己有权限的菜单,并在路由守卫中进行权限控制,防止手动输入路径导致非法打开页面。
其中一个页面是前端页面,比如首页,用户管理页面,资源管理页面等等。
基本思路是:前端路由不变,数据库保存菜单结构,页面权限控制(可直接做成页面方便管理)等,前端根据数据库中的菜单结构和权限信息渲染菜单并只显示自己有权限的菜单,并在路由守卫中进行权限控制,防止手动输入路径非法打开页面。
页面和路由需要在前端路由器(vue-router)中正常创建。
数据库存储菜单结构和页面权限信息。
菜单(目录,非内容页面)可以自己创建,不需要前端路由存在,因为这指的是菜单的可视化组织结构。
该页面(内容页)必须是前端路由中现有的页面,因为这是用户需要访问的内容。
菜单与页面构成层级关系,第一层可以是菜单,也可以是内容页,内容页也可以放在菜单下面,理论上(需要页面菜单样式支持)可以形成无限层级的菜单
菜单和页面的基本属性包括title(对应路由title)、name(对应路由name)、path(对应路由path)、parent、type(menu/page)、visibility(是否显示左侧菜单栏:部分页面可能在页面内链接),是否需要验证权限(部分页面如首页,无需验证权限,所有人都可以访问)
不需要管控权限、不需要在左侧菜单显示的路由可以不予管理,比如404页面等。
前台打开后,获取数据库的所有菜单、页面、结构,根据用户是否登录、是否需要验证权限等进行控制,或者如果用户没有权限,则将用户重定向到登录页面。
用户登录成功后,获取用户对应的页面权限列表,将上一步获取的所有页面、结构、用户权限列表渲染成菜单,菜单中只包含用户拥有的权限,提升用户体验,避免展示大量用户无法访问的菜单,影响使用,暴露不必要的功能。
在路由守卫中,每次跳转都会根据上一步得到的权限列表进行判断,如果没有权限,则可以返回404或者无权限页面,防止用户手动输入路径进行超越权限的访问。
细节:
登录:用户填写完账号密码之后,服务端会验证是否正确,验证通过之后服务端会返回一个token,获取到这个token之后(我会把这个token存放在cookie中,保证刷新页面之后能记住用户的登录状态),前端会根据这个token拉取一个user_info接口,获取用户的详细信息(如用户权限UI界面,用户名等)。
权限验证:通过token获取用户对应的角色,根据用户的角色动态计算对应的授权路由,并通过router.addRoutes动态挂载这些路由。
权限控制具体实现思路:
1)路由级别权限控制:
2)按钮级权限控制:
在前端,角色管理基本就是菜单管理,根据不同的角色展示不同的菜单,而且用户访问的时候需要判断当前用户是否有当前权限,否则用户无法访问,可以这样实现
使菜单可配置,其中包含以下字段
//路径
path?: string;
//图标
icon?: string;
//子菜单
children?: Array;
//菜单名字
text: string;
//菜单权限集合
auth?: Array;
同时编写一个递归函数来生成菜单角色权限设计像素游戏素材,并判断用户的角色来决定是否生成此菜单。
同时我会封装一个自己路由的高层组件,进去之前会判断你是否有权限访问这个地址,有的话就跳转,否则就跳转到没有权限的页面。
创建路线列表和菜单列表(左侧/顶部)。两者的格式类似。菜单是一个包含更多图标和其他内容的字段。
将路线列表分为两部分:登录后才可查看的(授权列表)和未登录即可查看的(访客列表)
给权限列表中的每个路由添加一个角色数组字段,使得只有其中的角色才能访问此路由
在路由配置文件中跳转新页面前添加导航钩子,将用户登录后返回的角色信息和权限列表进行对比,计算出用户可以访问的路由列表,并保存到vuex中
使用 router.addRoutes() 方法连接两个列表(Vue 框架)
同样的,可见菜单列表计算并赋值保存在vuex中
显示页面
1、首先将角色管理界面布局为表头搜索区域和表格内容区域,表头搜索使用el-form组件即可。数据绑定方面,添加下面分页组件的数据,这样调用查询接口的时候数据会更方便。表格内容没什么好说的,直接用el-table就行。
2.添加角色和编辑角色功能可以使用同一个组件,但是状态不同,一个是编辑状态,一个是添加状态。数据直接在父组件中配置角色权限设计,如果是编辑就设置这个角色的数据,如果是添加就设置一个空白的数据。保存后调用自定义事件刷新页面。
3.分配菜单没什么,只是一个el-tree组件加上节点点击事件的处理
4、使用v-for循环出多个el-checkbox-groups来展示资源分配页面。每个资源都有一个分类,如果该分类下的所有资源都被选中,则该分类为全选状态,否则为半选状态。点击分类时,判断当前分类状态,如果半选,则设置为全选,并选中该分类下的所有资源。如果当前分类未被选中,即该分类下没有资源被选中,则设置为全选,如果是全选状态,则该分类下的所有资源都为未选中状态。
1、关于新增与编辑
这里用的是添加角色与编辑角色用的是一个公共组件,列表中通过是否是字段来通过路由来进行props传参,新增与编辑显示的文案以及调取的借口不同等,如果是新增增什么都不出现,如果是编辑,则获取之前的详情并且回显
2、关于分配菜单
复选框树状结构,通过是否勾选来控制分配菜单
按功能拆分模块
filter 函数使用 el-form 拆分成一个组件,当点击“搜索”按钮时,传入页面的参数和查询
添加角色按钮弹出模态窗口
· 底部表格相关 · 表格拆分组件
· 分配菜单 和 分配资源 跳转到相应的页面
· 删除事件传 ID 给页面,在页面中调用接口删除 cell,成功后调用 table 列表接口
· 编辑 弹出 modal 窗 并调用 当前 cell 详情的接口,并把服务端返回的角色详情数据回填到 modal 页面对应的数据
Vue 实现
目前主要的设计思路是基于Vue-Router,后端返回角色权限定义,后端返回路由权限数据对应的角色,返回格式为 { role: 'admin', permissions: ['Order', …] },
其中permissions对应前端路由页面名称,这样后端就可以动态返回该角色所拥有的权限列表,前端配合router.addRoutes可以动态注册路由,实现路由级别的权限控制。
在后台管理系统中,权限是分配给角色的(包括页面权限和接口权限),页面权限可以基于vue-router API动态生成路由表,而接口权限需要后端同学验证。
Vue 中权限控制的主要思想是,前端会有一个路由表,标明每个路由可以访问的权限。用户登录后,通过 token 获取用户的角色,并根据用户的角色动态计算出对应的授权路由,然后通过 router.addRoutes 动态挂载路由。但是这些控制只是页面级别的。
在创建vue实例的时候会挂载vue-router,但是此时vue-router会挂载一些需要登录或者不需要权限的公共页面。当用户登录后,获取角色,将角色与路由表中每个页面需要的权限进行对比,生成最终用户可以访问的路由表。调用router.addRoutes(store.getters.addRouters)添加用户可访问的路由。使用vuex管理路由表,根据vuex中可访问的路由渲染侧边栏组件。React实现
React:使用高阶组件包装路由视图以进行权限控制
文章来源:https://blog.csdn.net/weixin_40599109/article/details/113728974