数据权限
作者:唐亚峰 | battcn
字数统计:492 字
多维度数据权限
为保障不同决策身份的用户数据安全,会将划分每个用户可见的数据范围
- 全部:可以看所有的数据(常为管理员角色)
- 本级及子级:常用语组织架构领导层
- 本级:用处较少,常用部门组长之类的
- 自定义:可以根据自己业务场景自定义权限范围和资源
- 个人:顾名思义,只能看自己创建的数据
wemirr-platform
只需进行少量的规则代码配置,即可实现灵活多维度的数据权限控制。
使用方式
手动使用
手动API调用,通过 DataPermissionUtils.execute()
方式构建 DataPermissionRule
即可
java
@GetMapping
@Parameters({
@Parameter(name = "name", description = "名称", in = ParameterIn.QUERY),
@Parameter(name = "principal", description = "账号", in = ParameterIn.QUERY)
})
@Operation(summary = "查询日志 - [DONE] - [Levin]", description = "查询日志 - [DONE] - [Levin]")
@PreAuthorize("hasAuthority('log:login:page')")
public Page<LoginLog> query(PageRequest request, String name, String principal) {
return DataPermissionUtils.executeDefaultDataPermissionRule(() ->
loginLogService.page(request.buildPage(), Wraps.<LoginLog>lbQ().like(LoginLog::getName, name)
.like(LoginLog::getPrincipal, principal).orderByDesc(LoginLog::getCreatedTime)));
}
注解使用
可以指定多个字段多个维度的数据权限,可以自行灵活定义
java
@DataScope(columns = {
@DataColumn(name = Entity.CREATE_USER_COLUMN,resource = DataResourceType.USER),
@DataColumn(name = "company_id",resource = DataResourceType.COMPANY),
})
IPage<UserResp> findPage(@Param("page") IPage<User> page, @Param("req") UserPageReq req);
核心实现
基于 MP 提供的 MultiDataPermissionHandler
实现了动态多维度数据权限
java
@Slf4j
@RequiredArgsConstructor
public class DataScopePermissionHandler implements MultiDataPermissionHandler {
private final AuthenticationContext context;
@SneakyThrows
@Override
public Expression getSqlSegment(final Table table, Expression where, String mappedStatementId) {
// 匿名用户不进入数据权限插件
if (context.anonymous()) {
return null;
}
if (log.isDebugEnabled()) {
log.debug("sql statementId{},where - {}", mappedStatementId, where);
}
// 默认从当前线程上下文获取,兼容 DataPermissionUtils.executeWithDataPermissionRule 方式
DataPermissionRule rule = DataPermissionRuleHolder.peek();
if (rule == null) {
// 注解的优先级最低
rule = DataPermissionUtils.getDataPermissionRuleByMappedStatementId(mappedStatementId);
}
return buildAnnotationExpression(table, rule);
}
private Expression buildAnnotationExpression(Table table, DataPermissionRule rule) {
if (rule == null) {
return null;
}
final DataPermission permission = context.dataPermission();
if (permission.getScopeType() == DataScopeType.ALL || rule.isIgnore()) {
return null;
}
final List<DataPermissionRule.Column> columns = rule.getColumns();
final List<Expression> conditions = DataPermissionUtils.buildConditions(context, table, columns);
if (CollUtil.isEmpty(conditions)) {
return null;
}
// 使用循环将条件逐个与前面的条件组合起来
return conditions.stream().reduce(AndExpression::new).orElse(null);
}
}