# 权限控制设计 重要
权限控制主要分为前端菜单、页面按钮及后端接口控制,一个安全严谨的系统在这几个方面缺一不可,尤其是后端接口的权限控制,当然如果一些对权限安全方面要求不是很高的系统,控制好前端也是可以的了。
题外话
我见过了非常非常多的企业内部管理系统,后端接口的权限控制非常简单,只需有登录的用户就都可以访问。也就是只要我知道接口地址,那哪怕我只是一个普通没有权限的用户,我也可以随便调用接口访问我没有权限的功能。
系统目前是以读(Read)、写(Write)、审核(Review)三个类型进行权限限制,当然这个可以由开发者进行修改的。
具体的权限控制是在角色管理菜单进行配置的,如下图所示,勾选了菜单前面的复选框,说明该角色拥有该菜单的页面访问权限,勾选后菜单的读、写、审核复选框才可选(菜单所具有操作权限需根据菜单的权限配置),勾选对应的操作权限后,该角色拥有菜单对应的操作权限,也拥有菜单的接口上对应权限接口访问权限。
# 前端元素控制
就是控制没有权限的用户打开页面后,相关权限按钮或其它元素被隐藏或禁用了,例如没有读权限的用户,打开页面后,发现查询按钮是灰色的,列表没有数据,没有写权限的用户,创建跟编辑按钮是灰色禁用或者隐藏了。
最初我是想用指令,例如v-permission:read
类似这样,然后没有权限就隐藏元素,但后面发现这样太不方便了,例如有些用户可能不想隐藏,想禁用,或者要显示一个提示之类的。最终还是用方法返回Boolean值的方式,这样处理起来更灵活。
我在Vue
对象注入了$permission
对象,可以用this.$permission
访问这个对象,这个对象提供了4个判断是否有对应权限的方法,可详见前端源码/src/utils/permission.js
文件,开发者可根据方法返回的Boolean
值对前端元素进行隐藏或者禁用。
//以下4个方法均返回Boolean类型的值
//判断当前用户在用户管理菜单上是否有读权限
this.$permission.canRead("sys.user")
//判断当前用户在用户管理菜单上是否有写权限
this.$permission.canWrite("sys.user")
//判断当前用户在用户管理菜单上是否有审核权限
this.$permission.canReview("sys.user")
//判断当前用户是否有用户管理菜单权限
this.$permission.hasMenu("sys.user")
例如,我需要没有写权限的用户,它的创建按钮是要灰色禁用的,就可以这样处理了,相当灵活。
<el-button
type="primary"
:disabled="!$permission.canWrite()"
@click="create" >创建
</el-button>
# 严格权限的组件设计
如果某些组件需要严格的权限控制的话,一般将写成两个组件,一个公共组件,一个非公共组件。
- 非公共组件:组件上面所用的接口一般是用非公共类型的权限接口。
- 公共组件:用于被其它组件引用,组件上面所用的接口一般是用公共类型的接口;
例如
一个系统里的员工列表需要被很多其它组件所引用,如果只用一个组件一个接口,那这个组件里的接口必须得定义为公共接口。然后在每个需要引用到员工列表的菜单接口配置里加上此公共接口。
如果说员工列表有很多机密字段,不能随便被查看,那么可以创建两个组件,一个有全部字段的列表,用的是非公共接口,一个仅有公共字段的列表,用的是公共接口,那么在员工档案的菜单接口配置的权限接口上加上非公共接口,在其它要用到员工公共列表的菜单接口公共接口上添加公共接口。
# 后端接口控制
在你需要添加权限验证的接口的控制器上加上这个特性[Authorize(AuthorizationPolicies.AuthorizationPolicyNames.ApiPermission)]
就会启用接口的验证了。
提示
如果后端的接口没有添加在接口管理里,而后端接口加了这个特性了,那统一会返回无接口权限权限的提示。