数据权限,资产管理

    为了兼容之前版本的租户功能,默认此功能未开启.可根据需求通过配置进行开启.

    场景一:

    1. 当用户和任意org关联时,用户只能管理和用户关联的org下的数据。
    2. 当用户没有和org关联时,如果用户不是租户管理员,则只能管理分配给自己的数据.如果是租户管理员则可以管理全部租户下的数据.
    3. 当用户即没有和org关联,也没有和租户关联,则能管理平台的所有数据

    场景二:

    1. 当用户和任意org关联时,用户只能管理自己创建和分配给自己以及用户关联的org下的数据。
    2. 当用户没有和org关联时,用户只能管理自己创建和分配给自己的数据
    1. jetlinks:
    2. assets:
    3. enabled-dimensions: user,org # 开启数据权限控制的维度
    4. auto-binding: true # 在进行新增和删除时是否自动绑定解绑
    5. dimension-exclude-asset-types: organization #机构是租户的资产,但是是维度,所以不进行维度绑定
    6. tenant-member:
    7. enabled: false # 关闭基于原版租户的权限控制

    实现原理

    通过Authentication#getDimensions来获取当前用户已绑定的维度Dimension信息,并根据维度信息创建对应的资产持有人AssetsHolder信息.

    利用AOP,拦截对应的controller方法,根据注解AssetsController中的相关配置进行控制:

    1. 动态查询(QueryParamEntity)将被注入条件DimensionAssetsTerm.查询数据时,会自动添加数据权限控制查询条件.(仅支持关系型数据库)
    2. 默认会将方法的第一个参数当成资产ID,使用注解AssetsController.type值作为资产类型,获取资产绑定AssetsHolder.getBindings信息并进行权限控制.
    3. 如果设置了AssetsController.assetObjectIndex,则会将对应索引的方法参数当成资产对象进行处理,使用AssetsController.property当作资产ID属性从资产对象中获取资产ID进行控制.

    平台已有的维度类型:

    1. user: 用户
    2. : 租户
    3. org: 机构

    平台已有的资产类型:

    1. organization: 机构也是一种资产
    2. product: 产品
    3. device:设备
    4. deviceGroup:设备分组
    5. deviceCategory:设备分类

    其他实现AssetType接口的枚举.

    自定义维度

    实现接口DimensionProvider并注入到spring.

    1. 定义资产类型: 实现接口AssetType或者EnumAssetType.例如:
    1. 定义资产提供者:实现接口AssetSupplier
    1. @Component
    2. @AllArgsConstructor
    3. public class MyAssetSupplier implements AssetSupplier {
    4. private final ReactiveRepository<CustomEntity, String> repository;
    5. @Override
    6. public List<AssetType> getTypes() {
    7. return Arrays.asList(MyAssetType.values());
    8. }
    9. @SuppressWarnings("unchecked")
    10. public Flux<DefaultAsset> getAssets(AssetType type, Collection<?> assetId) {
    11. return repository
    12. .findById((Collection<String>) assetId)
    13. }
    14. }
    1. 声明式数据权限控制
    1. 编程式权限控制
    1. public Mono<Void> method(MyEntity entity){
    2. //更多操作看AssetsHolder接口
    3. return AssetsHolder
    4. .assertPermission(MyAssetType.custom,Arrays.asList(entity.getId()))
    5. .then(doSomeThing(entity));
    6. }

    自定义资产权限控制

    实现AssetsHolderProvider接口,并根据用户信息返回AssetsHolder.

    1. tenantId: 租户ID,当用户为租户管理员时,以此字段进行查询
    2. members: 租户成员ID,当用户为非租户管理员时,以tenantIdmembers组合查询
    3. bindins: 维度绑定信息,当用户绑定了维度,并且开启了资产维度数据权限控制时,以此字段进行查询

    bindins的值规则为: md5(dimensionType+"|"+dimensionId).

    如果需要对ElasticSearch存储的相关数据进行数据权限控制,可以在存储数据时,添加对应的字段. 平台已经对设备数据统计支持了数据权限控制.

    查询时的权限控制: 可以利用AssetsHolder.injectQueryParam来注入数据权限控制条件.例如:

    也支持嵌套类型字段

    1. AssetsHolder
    2. .injectQueryParam(param,"device", "tags.deviceId")//资产类型和id属性可以为任意值,因为最终会被替换为实际的字段
    3. .flatMapMany(this::doQuery)

    注意

    平台内对大部分功能都默认开启了数据权限控制,但是部分功能 如: 设备接入,规则引擎中的脚本等面向开发运维人员的功能,可能会对系统造成安全问题,不建议开放终端用户.