CloudDM权限系统设计

前言

CloudDM是我创业时参与开发的第二个项目,主要用于企业数据安全的查询与管理。今天和大家分享下CloudDM权限系统的设计。CloudDM的RBAC模型总体上也参照RBAC0来进行设计,但是根据自己产品的需要做了一些变化。

传统RBAC0权限模型

传统的RBAC0模型如下图所示,主要的特点如下:

  • 用户关联角色,角色关联权限。用户拥有的权限有其所属的角色的集合来定义
  • 用户、角色、权限之间关系均为多对多

image.png

CloudDM的RBAC权限模型

CloudDM的权限模型如下所示,主要特点如下:

  • 一个用户只关联一个角色: 这样设计的理由是权限体系主要服务CloudDM产品,我们产品中一个用户关联一个角色已经可以满足大部分场景,没必要引入用户和角色之间的多对多关系增加系统复杂度
  • 一个角色关联多个权限:用户可以自由创建

image.png

权限类别划分

页面权限/功能权限/资源权限/数据权限

一个典型的带用户UI界面的应用系统一般可以划分为如下四类权限。

  • 页面权限:页面上哪些组件、按钮可以展示
  • 功能权限:和业务功能对应,例如电商场景的“添加到购物车”、“下单”等功能
  • 资源权限:特定的资源单位,涉及资源访问的,只有资源的拥有者才可以操纵资源。用户即使被授予了功能权限,如果没有特定资源的权限,执行相关功能的时候仍然会报错
  • 数据权限:侧重于用户能看到的数据内容。例如你拥有“查看用户订单”的功能,但是如果你没有对应用户的数据权限的话,自然也是无法看到罗列的订单数据的。在CloudDM产品中,主要指的就是数据库内的数据,需要有数据权限才可以访问。

在CloudDM中根据不同的访问情况,权限的校验层数有所不同:

不涉及资源的功能操作(2层校验)

image.png

涉及非数据库资源的功能操作(3层校验)

image.png

涉及数据库资源的功能操作(4层校验)

image.png

CloudDM权限分类

clouddm总体上在权限分类划分上遵循了以下的设计准则:
image.png

  • 细粒度:权限的粒度较细,每个Controller方法均对应一个具体的权限
  • 易实施:基于Controller方法注解以及拦截器统一处理,开发时可以比较便利的对新增的功能添加权限,参考下图创建集群功能,基于注解和权限枚举值结合,即可定义接口的权限归属。具体的一个权限实例通过新增一个枚举值,即可新增一个权限定义。

权限注解使用案例

1
2
3
4
5
6
//RequestAuth注解定义了该Controller方法关联的权限定义,用一个枚举类表示CLUSTER_CREATE
@RequestAuth(value = { CLUSTER_CREATE })
@RequestMapping(value = "/createcluster", method = RequestMethod.POST)
public ResponseData<?> createCluster(@Valid @RequestBody CreateClusterFO createClusterFO, HttpServletRequest request) {
// 只有通过拦截器的权限验证才能进到这个方法体内
}
  • 多层级:一个功能权限定义由以下几部分组成。二层类目设计可以更好的组织细粒度的每个权限,保证了灵活性。国际化的名称可以提供前端展示。后端定义好一个功能权限实例的结构,前端展示的能容也随之确定。

权限枚举值定义

1
2
3
4
public enum MyRole {
ROLE_NAME(I18N_ROLE_NAME, FIRST_I18N_CLASSIFY_NAME,
SECOND_I18N_CLSSIFY_NAME);
}

image.png

  • 易使用:用户侧使用的时候能够看到组织良好的权限,按需开启即可

image.png

权限设计

页面权限&功能权限

在CloudDM的设计中,页面权限是根据功能权限来定义的,这样的好处是不需要再单独针对页面权限设计一套权限数据。根据功能权限的情况即可推到出当前登入的用户有哪些页面权限。在CloudDM中,页面权限的定义更为宽泛,即一个**前端组件/安全的展示权限,**如果有页面权限,即表示用户对该组件/按钮是可见的。

根据功能权限可以推导用户的页面权限。页面权限关联的功能权限可以是其不同维度上的,它可以和不同维度的功能权限去映射,来判断是否有页面权限。这里我们先假设存在如下的功能权限实例:

  • 系统管理(一级类目)
    • 数据源管理(二级类目)
      • 添加阿里云数据源(具体权限)

下表显示了三种页面权限关联功能权限的例子。

页面权限 映射的功能权限维度 功能权限维度名称 备注
顶部导航栏“系统设置”一栏的显示权限 一级类目名称 系统管理 只要系统管理一级类目下有被授予权限的,这个按钮即可展示
侧边栏数据源管理按钮显示权限 二级类目名称 数据源管理 只要数据源管理二级类目下有被授予权限的,这个按钮即可展示
添加数据源按钮显示权限 具体权限 添加阿里云数据源 必须有最细粒度的功能权限才可以显示按钮

image.png

资源权限

CloudDM的资源权限维护在一个数据库表中。在特性资源创建后,会往资源权限表内写入记录,将人与资源权限关联起来。用户操纵特定资源的时候,会去检查对应的资源权限。

数据权限

在CloudDM产品中,数据权限主要指的即数据库实例上数据的访问权限。数据权限有自己独立的授权页面。针对数据库本身的特征,数据权限的授权可以基于数据库不同的粒度上进行授权。在CloudDM中,当前支持的授权粒度为库,后续也会慢慢优化到支持表和列权限。
image.png

权限与角色&用户之间的关系

在RBAC权限模型中还有角色和用户的定义,这在CloudDM中也同样存在。在标准的RBAC模型中,权限都是与角色关联的,判断是否有权限时是通过判断用户所属角色是否含有相关的权限来决定是否通过权限验证。但是在CloudDM中则略有不同。在CloudDM中,页面和功能权限是与角色关联的,而数据和资源权限是与用户关联的。
image.png

之所以这样设计的原因是:

  • 权限数据隔离:除了页面权限和功能权限的权限数据可以一起定义比较合理之外,其他权限层次的权限数据的关系存储都是隔离的,这样在代码架构层次上会比较清晰。如果将不同层次的权限的实现方式杂糅在一起,在代码实现层面就会显得混乱。
  • 交互使用上更合理:功能、页面权限按照RBAC基于角色去管理权限在web应用中是十分常见和符合用户使用习惯的。而在CloudDM中定义了诸多资源,这些资源绑定到用户(或者组织)则是更为合理的选择。现在CloudDM还没定义“组织”这样的实体,因此现在都是绑定到人的。用户配置权限的时候可以较为清晰的感受到CloudDM设计的权限层次:
    • Web应用的功能权限由角色去定义(Web功能权限):用户可以自己配置某个用户属于某个角色,而这个角色又可以定义其拥有web侧的哪些权限
    • 不是自己的资源无法操作(资源权限):即使有功能权限,但是如果资源不是属于自己的,也是无法访问的
    • 针对数据库资源,还需要走额外的数据授权才可访问:作为特殊并且重要的资源,权限把控更为严格,除了验证资源所属之外,还要有细粒度的库授权,才可以真正访问库上的数据

主子账号设计

考虑一般公司的运作方式,一般会有统一的管理员来负责资源的管理、权限的分派授予。在这种客观条件下,设计主子账号来配合权限体系是比较合理的。

CloudDM的主子账号体系拥有以下特性:

  • 主子账号关联:通过标准方式注册的账号为主账号,通过主账号的子账号创建出来的账号为子账号,并且这些子账号是关联在这个主账号下的
  • 资源关联实体只能为主账号:子账号如果被授予相关功能权限,则也是可以创建资源的,但是资源关联的用户实体全部会绑定到其主账号上
  • 子账号的资源权限校验会以其关联的主账号权限数据来检查:因为资源的关联人均为主账号,所以权限校验时都是以主账号的权限数据来判断
  • 数据库资源关联的主账号拥有资源下所有库的数据权限:数据库资源的添加者对应的主账号被认为是资源的owner,因此其下所有库均是有权限的,这样他才可以在后续过程中给别的子账号做库的数据权限授权
  • 子账号创建的子账号均归属于一个父账号:确保只有2级的父子账号层级

综合来说,CloudDM的主子账号体系拥有如下的优点:

  • 权限配置灵活:子账号可以配置不同的权限粒度和权限级别。权限授予级别高时可以执行一些高权限的管理,例如子账号管理、角色管理等
  • 资源归属清晰:资源只属于主账号,资源权限层次清晰。子账号访问资源均已父账号的身份进行