权限

根据不同的用途,系统提供4种权限,分别是功能权限、界面权限、API 权限和数据权限。

权限 用途
功能权限 控制功能树上显示哪些页面,用户能访问哪些页面,作用于门户的功能树和页面
界面权限 控制用户能访问页面上的哪些组件(按钮、输入框、表格列、标签页等),作用于前端页面
API权限 控制用户能访问哪些服务,调用哪些后端的API接口,作用于请求
数据权限 控制用户能访问哪些数据集的 CRUD 操作,能访问某个数据集的哪些字段,
能访问哪些数据范围(比如查看自己、查看部门、查看公司层级的数据),以及控制关联查询的访问,作用于数据库代理 DBProxy

所有的权限都存储在企业门户应用的权限表 permission 中,表结构见下表

角色 ID 权限编码 权限名称 条件 类型 状态
authc *:/react/mobileapp/mobile/org-auth/org.w:get 组织 menu 1
  • 权限编码
    • 采用三段式设计,使用冒号作为分隔符,将命令划分为类型、操作、属性/对象三个层级。支持使用通配符进行设置,即::*为最大权限
    • 功能权限的权限编码: *:页面路径:get
    • 界面权限的权限编码: *:页面路径#界面权限标识:*
    • API 权限的权限编码: *:请求路径:请求方法
    • 数据权限的权限编码: *:UUID:sql
  • 条件
    • 数据权限的具体配置内容
  • 类型
    • 功能权限是 menu、界面权限是 ui、API权限是 service、数据权限是 sql

权限项

以 API 为例,一个 API 在未声明为权限项时,默认注册用户可访问。在声明为权限项后,只有有权限的用户才能访问。

权限项在服务元信息文件中的 authorize.permissions 中声明,例如

{
    "authorize": {
        "permissions": [
            {
                "id": "_react_mobileapp_mobile_org-auth_org.w",
                "code": "*:/{serviceName}/mobileapp/mobile/org-auth/org.w:get",
                "name": "组织",
                "type": "menu"
            }
        ]
    }
}

特别说明

企业门户应用架构中的权限服务,支持设置最低权限要求,默认为注册用户 authc,可以改为匿名用户 anonymous。表示未声明为权限项的内容,匿名用户皆可访问

功能权限

功能权限用于控制功能树上显示哪些页面,以及用户能访问哪些页面

这两者在页面是否声明为权限项时,有一些区别,见下表

权限项 功能树 打开页面
页面未声明为权限项 没有权限不显示 没有权限能打开
页面已声明为权限项 没有权限不显示 没有权限不能打开

实现原理

功能权限是对页面这个层级访问的控制,可以限制用户是否能访问这个页面。可以通过新建角色并分配功能权限来开启对本页面的访问。

数据库表写入

新建页面后,默认会在门户的数据库表中自动插入1条本页面的访问权限,但未指定角色。角色分配权限后,会自动新插入1条本页面的访问权限,并同时指定角色。

开发时设置写入的是门户的permission_debug表,运行时设置写入的是permission表。

其中code会描述是访问哪个页面文件,name为用户自定义的名称,type为menu(指功能权限),role_id如果未分配给角色则为空。例如:

1660648822168

访问约束

  • 前端约束

当配置好权限,并分配给角色、授权给用户后,在门户显示页面菜单时,会判断登录的用户是否拥有该访问权限,如果不存在,则页面菜单不会显示出该页面。

  • 后端约束

如果用户绕过页面菜单,直接访问页面的链接,则后端会进行判断并提示访问无权限,避免绕开前端的漏洞。

实现效果

以功能权限页面为例,功能权限功能会自动加入该页面权限,如下图所示:

1660185148028

设置权限后的访问效果如下:

  • 有页面访问权限

1660110077644

  • 无页面访问权限

门户菜单没有出现“功能权限”页面。

1660110250368

  • 绕过页面菜单直接访问页面链接

页面上会提示页面权限不足。

1660650795764

界面权限

界面权限是对页面上的组件这个层级访问的控制,可以限制只读或者隐藏相关组件,组件包括页面上加入的所有组件,比如文本、按钮、输入框、表格列、标签页等。

使用本功能需要从组件市场下载“界面权限组件”,并把界面权限组件、上下文组件这2个组件同时加到页面中。

实现原理

数据库表写入

新建界面权限后,默认会在门户的数据库表中自动插入1条权限,但未指定角色。角色分配权限后,会自动新插入1条同样的权限,并同时指定角色。

开发时设置写入的是门户的permission_debug表,当微服务注册到门户后,会写入到permission表中。

其中code会描述是哪个页面文件的权限标识,比如权限标识是gnqxymtabledisplay。name为用户自定义的名称,type为ui(指界面权限),debug_type为insert,role_id如果未分配给角色则为空。例如:

1660701033289

界面权限判断

当前端页面放置了界面权限组件后,平台会根据用户是否有授权的界面权限,来控制页面组件的只读、隐藏属性。

以以下配置为例,页面会根据权限标识(gnqxymtabledisplay),找到组件(tableColumn2),如果访问的用户没有该权限,则该组件设置为prop属性(hidden或者readonly),例如:

<item comps="tableColumn2" compsname="tableColumn2" id="default21" op="oneOf" permissions="gnqxymtabledisplay" permissionsname="功能权限页面表格列显示权限" prop="hidden"/>

实现效果

界面权限配置如下:

1660190085722

访问效果如下:

  • 有访问权限

1660110505268

  • 无访问权限

具体表现为:

1、输入框和操作按钮为只读,操作不了;

2、发布者这列被隐藏了;

3、标签页中的“有权限用户可见”这个页签被隐藏了;

1660110571190

API 权限

API权限是控制用户能访问哪些服务,调用哪些后端的API接口。作用于后端。

实现原理

数据库表写入

新建服务后,默认会自动插入1条本服务的访问权限,但未指定角色。角色分配权限后,会自动新插入1条本服务的访问权限,并同时指定角色。

开发时设置写入的是门户的permission_debug表,运行时设置写入的是permission表。

其中code会描述是访问哪个服务,name为平台自动生成的名称,type为service(指API权限),debug_type为insert,role_id如果未分配给角色则为空。例如:

1660742097327

访问约束

当用户访问服务时,页面会向后端发起服务请求(权限code描述的路径,比如/permissionandrolecase/main/service/weather),请求会根据API权限判断用户是否拥有该权限,如果无权限,则请求返回异常,提示无权限。

实现效果

以天气预报服务为例,API权限功能会自动加入该服务权限,如下图所示:

1660184961052

设置权限后的访问效果如下:

  • 有访问权限

1660184757281

1660184696456

  • 无访问权限

1660184867165

1660184876491

数据权限

数据权限是控制用户能访问哪些数据集的CRUD操作,能访问某个数据集的哪些字段(列权限),能访问哪些数据范围(行权限,比如查看自己、查看部门、查看公司层级的数据),以及控制关联查询、子查询的访问。

同时数据权限具备一些高级特性的能力,比如设置为“单独使用的列权限”、“只有返回的列在权限指定的列范围内时才应用”等。

数据权限作用于后端。

数据集CRUD访问权限

通过数据权限可以控制对数据集的查询、插入、更新和删除(CRUD)等操作的访问限制。

实现原理

数据库表写入

新建权限后,默认会在门户的数据库表中自动插入1条权限,但未指定角色。角色分配权限后,会自动新插入1条同样的权限,并同时指定角色。

开发时设置写入的是门户的permission_debug表,运行时设置写入的是permission表。

其中code是数据权限的标识,name为用户自定义的名称,type为sql(指数据权限),debug_type为insert,role_id如果未分配给角色则为空。例如:

1660702825438

_condition记录了该权限具体配置的内容,比如这里为CRUD的全部权限,没有限制访问字段和条件。其中S指查询数据,I指插入数据,U指更新数据,D指删除数据。截图如下:

1660703103682

访问约束

当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,请求会根据数据权限判断用户是否拥有该权限,如果无权限,则请求返回异常,提示无权限。

实现效果

CRUD的操作限制既可以单独设置(比如只能查询数据),也可以多选组合设置(比如可以查询数据和删除数据)。参考如下图所示:

1660118543837

设置访问限制后,在向后端发起请求时返回是否有权限的结果:

1660118803533

同时页面上也会提示异常:

1660119154463

数据集字段访问权限(列权限和行权限)

实现原理

数据库表写入

配置完权限后,会在数据库表写入相关内容。其中code是数据权限的标识,name为用户自定义的名称,type为sql(指数据权限),debug_type为insert,role_id如果未分配给角色则为空。例如:

1660787919525

_condition记录了该权限具体配置的内容,比如这里为信息表CRUD的全部权限,同时设置了访问字段和条件。

其中S指查询数据(比如限制只返回createTime,person,title,type等列字段),I指插入数据(比如限制插入type等于财务公告),U指更新数据(比如限制更新type等于财务公告,同时限制where type=财务公告),D指删除数据(比如限制where type=财务公告)。截图如下:

1660787837158

访问约束

当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,请求会根据数据权限判断用户是否拥有该权限,如果无权限,则请求返回异常,提示无权限。

实现效果

数据集字段的访问权限,可以设置以下几类:

  • 某些字段不返回或者不能插入/更新

1660127913032

  • 插入数据时可以判断插入的值是否符合要求

1660128491639

  • 更新数据时可以判断此次更新是否可以操作,更新的值是否符合要求

1660128505586

  • 删除数据时可以判断此次删除是否可以操作

1660128519571

设置访问限制后,在向后端发起请求时返回是否有权限的结果:

1660128111719

同时页面上也会提示异常:

1660128127151

数据范围访问权限(行权限)

通过数据范围访问的设置,可以约束用户可以访问哪些数据范围(比如查看自己、查看部门、查看公司层级的数据)。这里通过列权限以及“可用的表达式”的设置来实现。

实现原理

可用的表达式

常用的几个表达式有:

表达式名称 表达式
用户标识 ${/uaa/userinfo#user_id}
用户主部门 ${/context/opm/currentusermainorg?type=dpt#fid}
用户主机构 ${/context/opm/currentusermainorg?type=ogn#fid}
用户岗位 ${/context/opm/currentusermainorg?type=pos#fid}
当前日期 @{CurrentDate()}

可以通过表达式来设置 where 条件,比如 销售人员ID 等于 ${/uaa/userinfo#user_id},这样就可以限制登录用户只能查看自己录入的订单信息。

特别说明

  • 系统提供的关于用户的可用表达式,都是调用 API 获取返回值。同理,也可以调用开发者自定义的 API 获取返回值
数据库表写入

配置完权限后,会在数据库表写入相关内容。写入的关键内容主要是conditions属性,例如:

1660789500933

访问约束

当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,此时dbrest会根据权限设置改写sql语句,把where条件加上来限制用户访问的内容。

实现效果

以销售订单为例,普通员工只能查看自己的订单,不能查看其他人的订单;部门领导可以查看部门员工的订单;公司领导可以查看整个公司员工的订单。

录入销售订单数据时,需要录入销售人员ID为上下文组件的获取当前人员成员主键(),销售部门FID为上下文组件的获取当前部门主键全路径()

权限设置方式如下:

  • 普通员工只能查看自己的订单

查询条件设置为:销售人员ID = 用户标识。

1660132852403

  • 部门领导可以查看部门员工的订单

查询条件设置为:销售部门FID 包含 用户主部门。

1660132883622

  • 公司领导可以查看整个公司员工的订单

查询条件设置为:销售部门FID 包含 用户主机构。

1660133031798

实现效果如下:

  • 普通员工查看的数据范围

技术2是普通员工,只能看到技术2自己录入的订单。

1660133685125

  • 部门领导查看的数据范围

技术1是技术部的部门领导,可以查看整个技术部人员录入的订单。

1660133451285

  • 公司领导查看的数据范围

总经理是公司领导,可以查看整个公司人员录入的订单。

1660133633270

关联查询访问权限

在前端页面的数据集,设置关联查询后,join的表也会受到数据权限的约束。

LEFT JOIN

left join权限影响规则:

1、左表会同时受到左表列权限和行权限的影响;

2、右表只受到右表列权限的影响,不受行权限的影响(也就是where条件不起作用)。

以销售订单为例,销售订单的客户ID关联客户表,销售订单 left join 客户(客户为右表),设置客户表的查询数据权限(列只返回客户名称,且客户姓名需等于张三),则查询到的客户信息只有客户名称这个列,且客户只有张三。

客户表(右表)查询权限设置:

1660719650218

关联查询结果(没有返回客户手机号码这列,且客户姓名没有过滤张三这个条件):

1660721476557

RIGHT JOIN

right join权限影响规则:

1、左表只受到左表列权限的影响,不受行权限的影响(也就是where条件不起作用);

2、右表会同时受到右表列权限和行权限的影响。

以销售订单为例,销售订单的客户ID关联客户表,销售订单(左表) right join 客户(右表),设置销售订单(左表)的查询数据权限(只返回订单编码、销售部门和销售人员),设置客户表(右表)的查询数据权限(列只返回客户名称,且客户姓名需等于张三)。

销售订单(左表)查询权限设置:

1660720482508

客户表(右表)查询权限设置:

1660719650218

关联查询结果(销售2登录,但左表并没有过滤销售人员ID这个条件):

1660720574473

INNER JOIN

inner join权限影响规则:

1、左表会同时受到左表列权限和行权限的影响;

2、右表会同时受到右表列权限和行权限的影响。

同样以上边的设置为例,inner join 查询后的结果(左、右表都启用了过滤条件):

1660721740481

子查询访问权限

在前端页面的数据集,设置子查询后,子查询的表不会受到数据权限的约束。

以销售订单为例,设置了子查询为客户表,设置如下:

1660724477976

同时客户表设置查询数据权限:

1660719650218

客户表的数据权限只返回客户姓名(并没有返回主键),同时需要过滤客户姓名为张三,但返回的结果显示,子查询并没有经过数据权限的约束,如下图所示:

1660724888517

高级特性

单独使用的列权限

数据权限设置为“单独使用的列权限”,设置此属性目的是为了扩大列字段的权限范围。

以查询数据为例,如果存在多个查询权限,列字段默认会做交集返回。如果勾选了其中1个权限的“单独使用的列权限”,此时多个权限的列字段会做并集返回,扩大了返回的列字段范围。

使用场景

在一些使用场景中,有些用户角色需扩展原来权限返回的列字段,但又不想更改原来的权限,此时可以新建1个权限,把这个权限设置为“单独使用的列权限”,再授权给这些用户角色,这样可以添加返回的列字段了。

例子如下:

权限1列字段 权限1单独使用的列权限设置 权限2列字段 权限2单独使用的列权限设置 授权效果的列字段(并集)
客户姓名 手机号码、客户状态 客户姓名、手机号码、客户状态
实现效果

新建”单独使用的列权限“的查询数据权限前的访问效果:

1660728074418

新建后的访问效果(多了手机号码和客户状态的返回):

1660728288626

注意事项

设置该属性时需要注意以下情况(不能全部权限同时设置该属性),避免使用异常:

权限1列字段 权限1单独使用的列权限设置 权限2列字段 权限2单独使用的列权限设置 授权效果的列字段
客户姓名 全部列字段
客户姓名 手机号码、客户状态 全部列字段

只有返回的列在权限指定的列范围内时才应用

数据权限设置为“只有返回的列在权限指定的列范围内时才应用”,设置此属性目的是为了降低行权限的使用范围,只有在满足返回的列在权限指定的列范围内时,行权限才生效。

使用场景

在一些使用场景中,查看某些列字段的时候,需要设置过滤条件,如果查询的列字段不满足要求,就不需要这些过滤条件。

例如,用户要查看客户的手机号码,只看状态为有效的客户就可以了,状态无效的不需要查看。设置如下:

权限列字段 权限行权限 是否“只有返回的列在权限指定的列范围内时才应用”
客户姓名、手机号码、客户状态 客户状态 等于 1

案例说明如下:

案例 查询的列字段 是否满足权限设置的列字段要求 结果
案例1 客户姓名、客户需求 不满足 客户状态 等于 1 不生效
案例2 客户姓名、手机号码、客户状态 满足 客户状态 等于 1 生效
案例3 手机号码、客户状态 满足 客户状态 等于 1 生效
实现效果

在前端页面的数据集组件中,可以设置需要返回的列字段:

1660741830776

返回的列字段不满足权限设置要求的访问效果:

1660741748675

返回的列字段满足要求的访问效果(启用了客户状态 等于 1的过滤条件):

1660741526776

results matching ""

    No results matching ""