Appearance
数据权限
配置流程
配置数据权限,开发者在开发运营平台 - 资源维护页面配置类型为数据的资源。
数据类型的资源只能配置在菜单或视图下,且不能配置在 目录(折叠菜单) 下
上图在消息管理页面配置了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最小的
若用户访问数据权限的菜单时,该用户没有这个页面的任何数据权限,则使用默认数据权限。若该页面没有配置默认数据权限,则会报错!
实现原理
- 用户访问页面时,会调用后台接口
- Axios拦截器中统一封装当前页面的Path地址
编写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}
- 数据权限插件执行,将原始SQL根据数据权限拼接上条件。 详情见: DataScopeInnerInterceptor