通用权限管理系统的总结梳理及技术细节
一、基本权限管理系统
基本的权限管理系统,基本遵循RBAC(Role-Base Accese Control)的模式
基本模式,class和action分开
但我们实际业务中,我们多把class和action合在一起
如果是内容类,比如cms这种,我们一般采用拆开的方式,因为这种资源-操作拆分的方式有意义。
如果是审批类,比如oa系统这种,我们一般采用合并的方式。
二、通用权限管理系统
当业务越来越多,都需要权限管理系统的时候,通用权限管理系统就显得迫在眉睫。
而通用权限管理系统中,粒度划分尤为重要。
1.粒度划分
权限的最小粒度,一般以一个接口为一条权限。
比如 /bbs/create (代表论坛发帖) 这种接口为最小粒度,好处是便于管理。
而如果是 /bbs/create?cid=123&pid=456 这种,我们还是按照 /bbs/create 这种粒度划分,而里面的参数,一般的做法是在create这个接口里面再单独做权限判断。保证最小粒度的权限足够简单,权限管理部分职责单一,而与业务强耦合的功能放在业务里做。
也就是可以分成 平台权限和业务权限。
2.结构图
如图所示,通用权限管理系统中,用户可能会是域账号登陆,外部的域账号只与用户关联与系统无关。
为了适应不同场景,用户、应用、角色三者会关联成一张表。
这个表的作用是告诉系统,哪个用户在哪个应用下对应哪一个角色。
角色跟资源的关系还是跟普通的权限系统保持一致。
如 用户A 在 OA 下是 管理员,用户A 在 ACL 下是 用户。
通过这个对应关系,基本可以满足各种不同的应用场景。
而数据资源作为可选项,在某些场景下也可能存在。
如用户A 在 DZZ 游戏下是管理员,用户A 在DQY 游戏下是GM。
这里需要关注的一点是,这个表基本都是一个用户对应一个游戏为一条数据,而不会一个用户对应多个游戏为一条数据。这是因为首先权限系统比较复杂,我们这么做为了使权限管理更加简单不使问题复杂化。另一个原因是真实使用场景中,这种一对多的关系比较少,复用率很低,而且变化的时候不灵活。
三、实际应用场景的思考
对于B端产品,可能会有多个系统部署在用户机器上,比如一个机器上有OA和ERP系统,两套系统都需要账户体系和权限管理系统,这个时候就可以用通用权限管理系统互相打通。但是通用权限系统貌似减少了开发成本,但是也有可能维护成本极高,要使用不同的系统之间的差异。
因此,设计通用权限管理系统的时候,往往通用权限系统只做一部分最简单的,最基础的权限控制,而跟业务耦合的权限管理则在各自系统本身的业务逻辑里面。
所以,才有了文章开头的粒度问题。
我们的粒度一般分到URI级别,每一个请求没有个URI都是一个资源,一个资源对应一条权限。
比如用户发帖这种问题,发帖接口可能是一个接口,但是里面还会涉及到用户是否可以发图片的这种权限。
这种情况下,比较推荐的做法是用户发帖还是一个权限,由通用权限系统处理,而发图片权限,则再由业务逻辑判断。class+action这一层最好职责单一,不掺杂业务判断,这样比较好管理,同时保持通用权限管理系统的纯粹性。
四、关于菜单
在实际场景中,每个项目都有菜单,当业务场景比较单一的情况下,菜单也可以做到通用权限管理系统中统一处理。
一个菜单对应一个资源,也可以对应多个资源
一般流程为:应用获取菜单总数据,查询这个用户信息,再通过权限系统查询这个用户uid对应每个资源是否有权限,然后洗掉没权限的菜单,留下这个用户在这个应用下的菜单。
如图所示,菜单可以只跟用户关联,所有的操作都是从用户这个纬度进行查询,这也也保持了基础权限管理系统的完整性。
当然,菜单可以不做在通用权限管理系统里做在业务层里,具体问题具体分析。
五、其他
现实应用场景中,对于应用来说,简单的做法是用户的相关权限操作都去请求通用权限管理系统,能操作就返回true,不能操作返回false。但如果需要的权限请求非常多,也可以一次性全部取全,再业务层自己处理。
实际开发中,权限管理原则大部分是视图不做强限制,数据强限制。
用户如果足够多,且权限差不多是,会分成用户组进行管理。
用户权限的继承基本在实际场景下不会考虑,因为一旦后期用户权限发生改变,牵连过大。
而用户权限的互斥一般只在业务在使用,保证通用权限管理系统的可维护性和通用性,特殊需求业务自己要求就好了。