1、数据权限概述
1.1、什么是数据权限?
如果你想学习Java工程,高性能,分散,深入。 微服务、Spring、MyBatis、Netty源代码分析朋友可以添加我的Java高级互动: 787707172,群里免费分享阿里fzddh直播讲解技术,以及Java大型互联网技术视频
数据权限是控制系统用户对数据资源的可见性,一般说来,满足某些条件的用户只能看到在这些条件下相应的数据资源。 那么,最简单的数据权限就是用户只能看到自己的数据吧。 在正式的系统环境中,有许多更复杂的数据权限要求方案,包括:
领导需要查看所有下属的客户数据,员工只能查看自己的客户数据
经理a可以看到所有的企业客户,而经理b只能看到年销售额低于1000万的企业客户
角色a可以看到全国的产品数据,角色b只能看到上海的产品数据
这些需求也可以通过硬代码来实现,但随着业务的快速发展,对这种数据权限的需求在增加。 如果全部采用硬编码方式,一定会带来很大的开发和维护压力。
1.2、要素分析
从当前登录的用户来看,数据权限定义可以解释为当前登录的用户只能看到该用户权限范围内的数据资源。 由此,可以分析数据权限控制中的几个重要因素。
主体,也就是当前登录的用户。 读取器、角色等概念可以翻译为当前登录的用户是否为读取器,以及是否具有角色。
数据资源。 即,限制对象的系统数据。
条件规则。 这意味着当前登录的用户应用于特定数据资源的条件。
2、数据权限设计
理论上,用户在访问受控制的系统数据时,可以通过获取用户应用于该数据资源的条件规则并将该条件规则解析为SQL查询语句来实现对数据的权限控制。 但是,在实施过程中,存在很多难点。 例如,当前登录的用户适用以下规则:
客户数据:客户经理、包括、下属产品数据:销售地区、等于、上海订单数据:产品销售地区、等于、上海) [以及]客户营销经理、上海
考虑以下问题:
“客户管理器”“包括”“下属”如何解析为SQL语句? 合并多表查询时该怎么办?
[部下]系统根据当前登录的用户计算,上海由管理员在后台选择。 两种方式怎么兼容?
针对复杂多变的组合条件,应该如何设计?
如何确定应用于当前查询的条件规则?
如果一个用户有多个角色,而不同的角色为同一规则设置不同的值,该怎么办?
2.1、规则来源
名词:规则来源。 在本文中,您可以指向各个独立的数据规则定义,并为每个用户的规则元素设置特定的规则筛选器值。 此值用作数据查询时的筛选条件。 在上述规则中,“客户管理器”和“销售地区”都属于规则来源。
2.2、规则元配置
1 .规则元名称的部署。 可以设置表中的哪些字段的规则,以及如何将规则元素名称与表字段相关联。 (如上述规则的“客户管理器”、“销售地区”等,可以考虑在配置文件中维护规则名称与数据库字段之间的关系。
2 .规则元Value数据源部署。 正如上述规则的[部下]、[上海]所示,规则源的Value源有三种情况。
由后台管理员输入。
系统提供数据源,由后台管理员选择。 例如,所在地区[上海]
系统提供数据。 例如,[部下]
配置文件可以满足数据规则的配置要求,但规则元素越多,配置文件的维护就越麻烦。 我可以用spring-boot代替spring-mvc,用注释代替配置文件吗? 虽然每个数据规则最终都会控制数据库字段,但现在大多数系统都有Model层支持数据库中的表,因此大脑补充了很好的规则元配置方法。
@tablename('test ) )。
publicclasstestmodalextendsabstractmodel {
@datarule(name='规则元名称') )。
私有字符串名称;
}
@DataRule注释源如下:
@target(elementtype.field ) ) ) )。
@ retention (retention policy.runtime ) )。
公共@接口数据rule {
//*
*规则元名称
*/
String name () default ' );
//*
*规则元值类型
*/
RuleSourceStrategy strategy () default RuleSourceStrategy.TEXT;
//*
*如果数据源是用户选择的,则{ @ coderulesourcestrategy.choice }数据地址
*/
字符串URL (默认);
//*
*如果数据源是系统提供的,则{@c
ode RuleSourceStrategy.SYSTEM}提供器类名*/
Class extends IDataRuleProvider> provider() default NullDataRuleProvider.class;
}
系统启动时,将规则元配置信息(名称、对应数据表、对应字段、值来源类型,值来源url,值来源提供者类名等)同步至数据库。数据表简单设计如下图:
2.3、数据规则的配置
有了规则元信息,管理人员即可在系统中针对不同用户(角色)设置规则元Value,该值作为数据查询时的筛选条件。规则元Value数据源包含三种情况,其中第①、②种情况下,需要管理员填写或选择该规则的值,存储于数据库;第③种情况下,Value值根据当前登录用户计算得出,也即是@DataRule注解中provider计算得来的值。由数据库存储的规则与系统计算得到的规则合并后即是登录用户的所有数据规则。
一个简单的配置界面如下:
2.4 数据规则的解析
由上文可知,适用于当前登录用户的数据规则主要来源有两种:
存储在数据库中的规则配置;如:所在地区[上海]
需要系统计算的规则配置;如:[下属人员]
两种情况下获取的数据规则合并之后即可获取适用于当前登录用户的数据规则集合,流程图如下:
两种情况下获取的数据规则如何兼容?规则合并后成为一个复杂的查询条件应该如何设计?
定义通用的规则结构如下:
{
rule:[{
field: "name",
operate: "equal",
value: "xxx"
}],
operate:"and",
group:[{
rule:[],
operate:"greater",
group:[]
}]
}
数据库存储规则结构的JSON串,合并时将JSON串反序列化之后使用and与系统计算得出规则对象连接即可,合并后的规则结构解析成简单SQL语句已经不是很难了。
但是对于多表联合查询时应该如何处理呢?
解析成SQL语句时可以使用表名+字段名的方式,可是遇到查询中使用别名的时候,这种方式也不能正常工作,这里暂时的处理方式是支持解析时传递别名。
一个用户拥有多个角色,不同角色对于同一个规则设置不同的值应该如何处理?
譬如,用户A拥有角色role1、role2,其中:
role1适用规则:[销售地区] [等于] [上海]role2适用规则:[销售地区] [等于] [北京]
那么用户A合并后的数据规则应该是:
用户A适用规则:([销售地区] [等于] [上海]) or ([销售地区] [等于] [北京])
即:一个用户对于同一个规则元的多个规则设置,应使用or连接后再与其他规则元进行and连接。
2.5、确定当前查询适用的数据规则
经过上述的规则配置与解析之后,我们很容易拿到当前用户适用的数据规则集合。但是在一次查询时我们应该使用集合中哪些规则进行过滤呢?一次查询是否开启数据规则过滤,使用哪些表的规则过滤应该是开发者来决定,类似:
xxxQuery(...).withDataRule("`table1`,`table2`");
即表示当前用户本次查询使用table1、table2中配置的数据规则。数据表中的每条规则应该支持在管理后台设置是否启用,这样理论上可实现每个用户对每一条数据规则的配置。
欢迎工作一到八年的Java工程师朋友们加入Java高级交流:787707172
本群提供免费的学习指导 架构资料 以及免费的解答
不懂得问题都可以在本群提出来 之后还会有直播平台和讲师直接交流噢