三、应用权限控制
我们认为,应用的权限控制可以分为如下四类:
菜单:用户在应用门户中可见哪些菜单可以通过权限控制
.按钮/链接:用户在门户页面中,哪些按钮可见可操作,可通过权限控制
.接口调用:不通过门户,直接通过客户端进行接口调用,接口是否允许调用可以通过权限控制
.数据:用户是否可见某些数据,能否操作可以通过权限控制
.菜单控制
菜单的控制其实比较简单。用户登陆成功后,前端会再来取一次用户的菜单项。后端服务根据用户分配的角色中,包含的菜单资源,在门户中组织出他所持有的菜单树。
但是菜单的组织过程,却也可以有一些不同。这里我们一种称为动态结构,另一种为静态结构。
动态结构首先要求菜单本身为树状结构,且菜单对应的页面(
中叫路由),图标等也记录在菜单中。整个菜单的层次结构,由菜单本身的树状结构表现。这种结构的好处是菜单配置非常灵活,菜单可以完全通过页面操作进行定制。这种结构适合经常需要动态变更的系统,且菜单配置人员对前端要非常地熟悉。另一种静态菜单结构,则菜单只需要一个平铺关系即可。菜单的层级,顺序,路由,图标等由前端定义,后端只定义用户可以用到哪些菜单。缺点是菜单定制不够灵活,但优点也很明显,非常便于前端开发,前后端分工更明确。
按钮/链接控制
有些系统中,会将按钮的权限与后端功能的权限分开设计为两个模型,但
中这两个合为一个叫做功能的模型。功能有唯一编码,这个编码在按钮上可控制按钮的显示,在方法上可以控制方法能否调用。按钮的控制也比较简单,特别是组件化的前端开发框架中。只需要为所有的按钮组件添加一个权限码定义,在页面渲染时,判断一下当前用户是否拥有这个权限码,有则显示此按钮,没有则将按钮从父组件中删除。
接口调用控制
在接口调用控制上,我们考虑过使用现成的一些控制方法,如
。但是它只能控制到角色级,虽然可以规则匹配,但仍然不够灵活。所以,我们基于功能编码,自行设计了一套。它的基本原理是,我们使用
,在每个需要控制的方法,添加了调用此方法需要的功能编码。方法被调用时,我们通过 对方法进行拦截,取得调用它所要求的功能码。然后我们在当前用户所拥有所有的功能码(在用户登陆时已查询出来放在 中了)中进行对比,如果存在就允许方法调用,否则抛出无权调用的异常。鉴于有些需要控制的方法可能在父类中,所以我们定义了两个
,一个定义在类上,可以配置父类上需要控制的方法。另一个定义在方法上,配置方法控制的权限码。查询方法调用所需权限码时,优先在方法上找到,找不到再到类上去查找。为了方便集成的应用实现接口调用控制,我们定义了一个抽象的方法权限切片处理类,封装了对方法调用的拦截过程。应用只需要继承这个类,配置需要拦截哪些接口即可。
数据权限控制
数据权限,我们认为数据权限 = 数据可见控制 + 数据操作控制。
而数据操作控制,通过按钮控制与接口调用控制组合,基本上可达到想要的效果。
那数据可见如何控制呢?我们归纳为两种:成员法与资源授权法。
成员法,就是用户如果为某个领域的成员,则他就可以看到这个领域,以及这个领域中的资源。如何实现呢?简单一点的办法,就是用户的某个角色,属于这个领域,就可以认为这个用户是这个领域的成员。像租户隔离,
中的项目隔离,其实就是用的这种方法。资源授权法,将某个精确的资源授权角色,或者直接授予用户。成员法实现数据可见控制有一个问题,就是粗度太大,不好实现更精确更细粒度的资源可见控制。要实现更细粒度的,可以使用资源授权法。但粒度细也就代表着管理复杂,孰好孰坏需要权衡后去使用。
推荐阅读
关于作者:将晓渔,现任普元信息云计算架构师。曾在 ,云计算,数据备份,移动互联相关领域公司工作,十年以上 工作经验。国内 云计算的早期尝鲜者,容器技术专家,微服务架构的践行者。