Skip to content

数据权限

配置流程

配置数据权限,开发者在开发运营平台 - 资源维护页面配置类型为数据的资源。

  • 数据类型的资源只能配置在菜单视图下,且不能配置在 目录(折叠菜单)

  • 上图在消息管理页面配置了7个”数据权限“,每个数据权限对应一个”数据范围“,每个数据范围都有1个代码层面的实现类。

  • 若某个菜单菜单或视图,需要配置数据权限,则一定得在此菜单下配置1个默认的数据权限。

编写实现类,开发者在acuity-cloud或acuity-boot项目中编写数据权限的自定义实现类。

系统中已经有6个实现类,其他的自定义实现类需要根据自身业务需求自己开发。

  • 6个内置实现类,分别为:查询全部数据、查询自己所在单位和单位的所有子单位和子部门、查询本单位、查询自己所在部门和部门的所有子部门、查询自己所在部门、查询自己的数据。

  • 1个自定义实现类。你可以参考此实现类,编写无数个自定义实现类。

配置数据权限插件。

注意:数据权限插件一定要在Mybatis plus的分页插件之前执行,否则分页数据可能不正确。

java
@Configuration
@Slf4j
@EnableConfigurationProperties({DatabaseProperties.class})
public class BaseMybatisAutoConfiguration extends BaseMybatisConfiguration {

    public BaseMybatisAutoConfiguration(DatabaseProperties databaseProperties) {
        super(databaseProperties);
    }

    @Bean
    public DataScopeInnerInterceptor getDataScopeInnerInterceptor() {
        return new DataScopeInnerInterceptor();
    }

    /**
     * 数据权限插件
     *
     * @return 数据权限插件
     */
    @Override
    protected List<InnerInterceptor> getPaginationBeforeInnerInterceptor() {
        List<InnerInterceptor> list = super.getPaginationBeforeInnerInterceptor();
       // database.yml 中 acuity.database.isDataScope=true 控制是否启用数据权限
        Boolean isDataScope = databaseProperties.getIsDataScope();
        if (isDataScope) {
            list.add(getDataScopeInnerInterceptor());
        }
        return list;
    }

}
@Configuration
@Slf4j
@EnableConfigurationProperties({DatabaseProperties.class})
public class BaseMybatisAutoConfiguration extends BaseMybatisConfiguration {

    public BaseMybatisAutoConfiguration(DatabaseProperties databaseProperties) {
        super(databaseProperties);
    }

    @Bean
    public DataScopeInnerInterceptor getDataScopeInnerInterceptor() {
        return new DataScopeInnerInterceptor();
    }

    /**
     * 数据权限插件
     *
     * @return 数据权限插件
     */
    @Override
    protected List<InnerInterceptor> getPaginationBeforeInnerInterceptor() {
        List<InnerInterceptor> list = super.getPaginationBeforeInnerInterceptor();
       // database.yml 中 acuity.database.isDataScope=true 控制是否启用数据权限
        Boolean isDataScope = databaseProperties.getIsDataScope();
        if (isDataScope) {
            list.add(getDataScopeInnerInterceptor());
        }
        return list;
    }

}

授权:租户的使用者在基础平台 - 角色权限维护 页面给数据角色绑定数据权限资源,并给角色绑定员工。

注意事项:

  • 同一个菜单或视图下的数据权限,只建议授权一个。由于 ant design 的Tree注解不支持单选树,所以这里做成了多选,后期先办法优化或加上限制。

  • 若同时给角色授权多个同级别的数据权限,会取sortValue最小的

  • 若用户访问数据权限的菜单时,该用户没有这个页面的任何数据权限,则使用默认数据权限。若该页面没有配置默认数据权限,则会报错!

实现原理

  1. 用户访问页面时,会调用后台接口

  1. Axios拦截器中统一封装当前页面的Path地址

  1. 编写Controller、Service、Manager、Mapper接口,Controller、Manager接口正常编写,Service、Mapper接口需要注意。

    • Service 接口的查询方法,不能加@Transactional注解,否则在执行数据权限拦截器时,会因为切换数据源失败报错!
    java
    @Override
    public IPage<Msg> pageByDataScope(IPage<Msg> page, Wrapper<Msg> wraps) {
      // 该方法不能加事务注解,否则会切换数据源失败!  @Transactional(readOnly = true)
      return superManager.pageByDataScope(page, wraps);
    }
    @Override
    public IPage<Msg> pageByDataScope(IPage<Msg> page, Wrapper<Msg> wraps) {
      // 该方法不能加事务注解,否则会切换数据源失败!  @Transactional(readOnly = true)
      return superManager.pageByDataScope(page, wraps);
    }
    • Mapper接口需要加 @DataScope 注解,同时配置@DataField,若pageByDataScope方法是多表查询,则可以配置多个@DataField,并为每张表指定别名。
java
@DataScope(value = {
        @DataField(alias = "m")  // m 就是sql中的表的别名
})
IPage<Msg> pageByDataScope(IPage<Msg> page, @Param(Constants.WRAPPER) Wrapper<Msg> wraps);

// xml 
SELECT  <include refid="Base_Column_List"/> FROM e_msg m  ${ew.customSqlSegment}
@DataScope(value = {
        @DataField(alias = "m")  // m 就是sql中的表的别名
})
IPage<Msg> pageByDataScope(IPage<Msg> page, @Param(Constants.WRAPPER) Wrapper<Msg> wraps);

// xml 
SELECT  <include refid="Base_Column_List"/> FROM e_msg m  ${ew.customSqlSegment}
  1. 数据权限插件执行,将原始SQL根据数据权限拼接上条件。 详情见: DataScopeInnerInterceptor

欢迎使用天源云Saas快速开发系统