# 数据(范围)权限控制
某些场景下的数据查询需要绑定一些强制条件,用于数据权限查看范围控制,如只能查看
本部门的
销售订单
数据。 不同于多租户的全局数据隔离,这种场景需要的是在这些特定业务功能里过滤查询条件,仅显示其权限范围内的数据,diboot 数据权限就是针对这种场景的解决方案。
# 使用步骤
示例场景:如
销售订单
业务对象有个部门id
字段,需要控制用户只能访问本部门的销售订单
数据。
实现步骤为: 加注解+写实现
# 1. 加注解:在需要控制数据范围的对象Entity中的过滤字段上添加@DataAccessCheckpoint注解。
示例代码:
// 销售订单对象,基于部门来过滤数据查看范围
public class SalesOrder extends BaseEntity{
// ...
// 数据权限检查点,按部门来过滤
@DataAccessCheckpoint
private Long orgId;
//...
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 2. 写实现:实现DataAccessInterface接口,返回当前用户可访问的合法ID集合
@Component
public class MyDataAccessPermissionImpl implements DataAccessInterface {
//如依赖了IAM组件,可选继承DataAccessPermissionUserOrgImpl实现
//public class MyDataAccessPermissionImpl extends DataAccessPermissionUserOrgImpl {
@Autowired
private IamOrgService iamOrgService;
@Override
public List<Serializable> getAccessibleIds(Class<?> entityClass, String fieldName) {
// 获取当前登录用户
IamUser currentUser = IamSecurityUtils.getCurrentUser();
// 提取其可访问ids
List<Serializable> accessibleIds = new ArrayList<>();
//按部门过滤
if(Cons.FieldName.orgId.name().equals(fieldName)){
//示例:可访问数据范围为: orgId 为 当前部门ID 或 子部门 IDs
Long currentOrgId = currentUser.getOrgId();
accessibleIds.add(currentOrgId);
List<Long> childOrgIds = iamOrgService.getChildOrgIds(currentOrgId);
if(V.notEmpty(childOrgIds)){
accessibleIds.addAll(childOrgIds);
}
}
// 按用户过滤
else if(Cons.FieldName.userId.name().equals(fieldName)){
//示例:可访问数据范围为: 本人
accessibleIds.add(currentUser.getId());
}
// 按其他字段过滤...
// 返回合法ID集合
return accessibleIds;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 3. Spring config类中配置Mybatis-plus数据权限拦截器,启用数据(范围)权限拦截
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 启用diboot数据权限拦截器,将拦截并修改需要控制数据权限的SQL
interceptor.addInnerInterceptor(new DataPermissionInterceptor(new DataAccessControlHandler())); // (v2.9及之后版本的添加方式)
// interceptor.addInnerInterceptor(new DataAccessControlInterceptor()); // (v2.8及之前版本的添加方式)
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
这样就可以针对SalesOrder数据查询的SQL中,强制添加 org_id IN(100001, 100002)
的过滤条件,实现数据访问范围控制。
# 4. 忽略某特定SQL的数据权限拦截 (since v2.9.0)
数据(范围)权限一旦启用,默认将会拦截所有针对该Entity的SQL查询,但某些情况下需要忽略某个特定SQL的拦截,该场景可以添加拦截忽略注解实现。
- 使用拦截忽略注解 @InterceptorIgnore 忽略某个查询
@Mapper
public interface XxxMapper extends BaseCrudMapper<Xxx> {
@InterceptorIgnore // 添加该注解后,数据权限拦截器将忽略该查询
long countAll();
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 基于岗位的范围控制
如果您的业务场景中数据权限范围跟岗位关联,不同岗位的用户可以访问不同范围的数据,可以结合diboot-*-admin前端岗位管理
功能中预置的数据权限
设置,实现前端配置后端控制。
diboot IAM组件也提供了后端的默认实现类 DataAccessPermissionUserOrgImpl 可供使用或扩展。
← 无SQL查询条件构建 数据加密与脱敏 →