1.本发明涉及数据权限控制方法技术领域,具体涉及一种基于注解的数据权限控制方法及系统。
背景技术:2.目前,在业务系统中,对数据权限控制的需求是非常常见的,比如某个列表页,需要根据用户的角色、机构等参数进行数据的过滤,以达到根据用户权限看到不同数据的目的。但是在实际开发过程中,往往会碰到开发已经写好sql,并且调试完成后,需求才提过来,这时候再改接口,需要调整接口参数(多传一个权限参数)、调整sql,可能会涉及到大量的改动,从而引发其他的bug。
3.如果有一项技术,能够让开发在不调整接口参数、不重写sql的情况下完成这项操作,就能非常好的解决上述问题。一种基于注解的数据权限控制方法就是这样一种技术,只需在相关的业务方法上添加注解,配置好权限参数,无需任何第三方依赖、没有多余的数据库访问、没有外部接口访问,就能完成对数据权限的过滤。通过这项技术,让数据权限与具体的业务sql解耦,在后续的调整中也更加的便捷和安全。
4.目前对于数据权限控制主要的实现方式包括基于外部接口提供的服务、直接修改业务sql、基于springaop的切面对sql进行二次处理。上述方式确实都能够实现对数据权限的控制,但是存在基于外部接口的方式,对外部接口形成了依赖,整体的性能和稳定性受外部接口影响,一旦外部接口性能不稳定或者宕机,将导致服务的不可用,稳定性太差。
技术实现要素:5.本发明针对上述问题,提出了一种基于注解的数据权限控制方法,解决了现有的数据权限控制存在基于外部接口的方式,对外部接口形成了依赖,整体的性能和稳定性受外部接口影响,一旦外部接口性能不稳定或者宕机,将导致服务的不可用,稳定性太差的缺陷。
6.本发明采取的技术方案如下:一种基于注解的数据权限控制方法,包括:当某个持久层方法被执行时,注解解析器会先解析该方法的方法签名,分析出具体执行的种类;在获取到方法签名后,注解解析器会提取方法上的注解信息;sql处理器根据方法签名获取该方法对应的原始sql语句以及注解解析器的解析结果;sql处理器将对注解参数进行计算,获取数据权限注解的字段名参数,作为sql条件中运算符左边部分,获取常量值或者动态参数作为运算符右边部分;在计算完所有条件表达式后,sql处理器会使用内层表达式参数,将各表达式关联起来,形成sql子句。本发明通过注解参数动态编译sql,不需要调整原来的业务代码和sql
语句,只需在相关的业务方法上添加注解即可,并且可自行控制起开或者关闭;由于注解是方法级的,当一个sql已经被使用在多个方法中,当一个方法被添加上注解,也不会影响该sql在其他方法中的正常使用,极大提高了灵活性。
7.可选的,所述数据权限注解包含权限表达式,其参数包括字段名、常量值和动态参数,其中字段名表示数据库表的某个字段名。
8.可选的,注解解析器在提取方法上的注解信息时,首先检查是否存在数据权限组合注解,如果存在数据权限组合注解,则解析权限参数,获取数据权限注解子集;如果不存在数据权限组合注解,则解析数据权限注解,该注解内部包含真正的权限表达式。
9.可选的,注解解析器提取方法上的注解信息时,找到方法上的每个数据权限注解,并放到一个数组中,然后遍历该数组,对数组中的数据权限注解实例进行解析,获取参数信息,并将最终结果封装成对象返回。
10.可选的,基于注解的数据权限控制方法还包括sql处理器在形成sql子句后,将子句与原始sql进行关联;如果原始sql中不存在条件子句,则在sql子句前拼接where关键字,然后拼接到原始sql。
11.可选的,如果原始sql中存在条件子句,则将外层表达式拼接至sql子句前,然后拼接到原始sql中。
12.本发明还公开一种基于注解的数据权限控制系统,包括:一注解解析器;所述注解解析器用于对业务方法上的注解进行解析,并提取出注解上的配置参数,并将注解参数抽象成具备一定格式的数据对象,解析的结果将会传递给sql处理器;以及一sql处理器;所述sql处理器用于获取原始sql、对注解解析器的解析结果进行计算,形成具备逻辑的sql子句,最后将原始sql与sql子句进行拼接,形成具备数据权限的sql。
13.可选的,所述注解解析器用于对组合注解的数据权限进行解析,发现其内部包含了两个数据权限注解,第一个数据权限注解中字段名是role_id;第二个数据权限注解中字段名是user_id;注解解析器根据上述信息,将注解转换成最终的sql子句。
14.目前对于数据权限控制主要的实现方式包括基于外部接口提供的服务、直接修改业务sql、基于springaop的切面对sql进行二次处理。上述方式确实都能够实现对数据权限的控制,但是存在一定的局限性,主要包括以下四点:a)基于外部接口的方式,对外部接口形成了依赖,整体的性能和稳定性受外部接口影响,一旦外部接口性能不稳定或者宕机,将导致服务的不可用,稳定性太差。b)直接修改业务sql的方式,属于硬编码的方式,一旦有业务变动,可能导致大量的代码需要修改,并且容易引出其他并发的bug,灵活性太差。c)基于springaop切面的方式,对第三方框架存在一定的依赖,在不同的框架体系下无法兼容运行,需要调整代码,同时会跟持久层框架提供的拦截器机制冲突,可能导致sql拼接异常,通用性太差。d)对逻辑复杂的条件无法很好的支撑,通常只是简单的提取用户角色或者部门,当出现需要同时满足某个角色又是某个部门的组合类场景时,不能够灵活的配置实现。
15.本发明通过注解的方式,将权限表达式作为动态参数写入注解参数中,通过注解解析器在本地对动态参数进行解析,不依赖任何外部服务或数据库,避免了因第三方原因而导致的服务稳定性问题。
16.本发明通过将权限处理的逻辑抽象至了持久层,利用持久层框架提供的sql条件拦截器对原生业务sql进行解析和二次封装,实现数据权限控制,整个过程遵循持久层框架对sql的处理流程,不会因为处理机制的不同而导致最终生成的sql出现拼接错乱;同时也不依赖外部mvc框架提供的拦截机制(如aop),使本方法能够兼容任何mvc框架(需引入持久层框架)。
17.本发明通过组合注解,实现对单一功能注解的组合,支持条件之间的“与、或“运算,提升了对复杂条件的处理能力,以便满足各种不同的业务需求。
18.(三)有益效果1、本发明通过注解方式实现数据权限控制,将权限控制逻辑与业务逻辑解耦,使数据权限控制操作具有很高的可操作性、扩展性很高,减少了对业务的影响。
19.2、本发明利用本地动态表达式机制,权限表达式解析和sql拼接过程不存在对外部服务或者数据库的访问,极大提高了整体的稳定性和性能,保障业务的稳定运行。
20.3、本发明通过组合注解,使注解表达式能够组合出具备一定复杂逻辑的条件子句,满足了对数据控制具有较高要求、较复杂的场景。
21.4、本发明使用持久层框架提供的拦截器机制,将数据权限控制流程委派给持久层框架执行,让数据权限控制与外部的mvc框架解耦,避免因为不同的外部框架而导致sql解析的顺序问题,从而具备更好的兼容性。
22.附图说明:图1是本发明的实施例2的一种基于注解的数据权限控制系统的工作流程图;图2是本发明的实施例2的基于注解的数据权限控制系统的mvc框架图;图3是本发明的实施例2的基于注解的数据权限控制系统的注解解析器的逻辑流程图;图4是本发明的实施例2的基于注解的数据权限控制系统的sql处理器的逻辑流程图。
23.具体实施式:下面结合附图和实施例,对本发明的具体实施方式作进一步详细描述。以下实例用于说明本发明,但不用来限制本发明的范围。
24.在本发明中sql表示结构化查询语言。本发明中的@datapermission表示数据权限。@datapermissions表示数据权限组合。outerexpression表示外层表达式。innerexpression表示内层表达式。and表示运算符。columnname表示数据库表的某个字段名称,valueconst表示常量值,valueexpr表示动态参数。
25.实施例1本发明公开了一种基于注解的数据权限控制方法,包括:当某个持久层方法被执行时,注解解析器会先解析该方法的方法签名,分析出具体执行的种类;在获取到方法签名后,注解解析器会提取方法上的注解信息;在提取方法上的注解信息时,首先检查是否存在数据权限组合注解,如果存在数据权限组合注解,则解析权限参数,获取数据权限注解子集;如果不存在数据权限组合注解,则解析数据权限注解,该注解内部包含真正的权限表达式。
26.提取方法上的注解信息时,找到方法上的每个数据权限注解,并放到一个数组中,然后遍历该数组,对数组中的数据权限注解实例进行解析,获取参数信息,并将最终结果封装成对象返回。
27.根据方法签名获取该方法对应的原始sql语句以及注解解析器的解析结果;sql处理器将对注解参数进行计算,获取数据权限注解的字段名参数,作为sql条件中运算符左边部分,获取常量值或者动态参数作为运算符右边部分;在计算完所有条件表达式后,sql处理器会使用内层表达式参数,将各表达式关联起来,形成sql子句。
28.sql处理器在形成sql子句后,将子句与原始sql进行关联;如果原始sql中不存在条件子句,则在sql子句前拼接where关键字,然后拼接到原始sql。
29.如果原始sql中存在条件子句,则将外层表达式拼接至sql子句前,然后拼接到原始sql中。
30.所述数据权限注解包含权限表达式,其参数包括字段名、常量值和动态参数,其中字段名表示数据库表的某个字段名。
31.实施例2如图1所示,本发明还公开了一种基于注解的数据权限控制系统在业务系统的业务输入和业务输出之间,包括注解解析器、sql处理器两部分。
32.其中注解解析器的主要作用是对业务方法上的注解进行解析,并提取出注解上的配置参数,并将注解参数抽象成具备一定格式的数据对象,解析的结果将会传递给后续的sql处理器进行处理。
33.需要注意的是,本实施例中,注解组合就是将多个单一功能的注解按照一定的逻辑进行组装,形成具备一定运行逻辑的,功能更复杂的高阶注解,一种基于注解的数据权限控制方法使用组合注解来实现注解的组合。基于组合注解,将只具备单一功能的注解进行组合,生成一条由多条件组合、具备一定逻辑、权限控制更精准的条件子句。
34.sql处理器的主要作用是获取原始sql、对注解解析器的解析结果进行计算,形成复杂的具备一定逻辑的sql子句,最终将原始sql与sql子句进行拼接,形成完整的具备数据权限的sql。最后将sql提交给jdbc驱动执行,完成业务操作。
35.整个权限控制过程不存在对外部服务的访问或者数据库的访问(业务数据访问不属于权限控制过程),仅对注解和内部的动态参数进行解析,具备良好的性能和稳定性。
36.如图2所示,本实施例的基于注解的数据权限控制方法,执行阶段在持久层框架的拦截器中,对于外部的mvc框架是无感的,不用关心外部的mvc框架是哪个体系的,具备良好的通用性和兼容性。
37.需要注意的是,本实施例注解解析器与sql处理器构成一个权限拦截器,本实施例中区别于servlet的过滤器和springmvc的拦截器,权限控制拦截器是持久层的一种拦截器,专门用于处理sql。在拦截器内能够获取原始sql、对sql进行自定义处理。权限控制拦截器用于对方法上的注解进行解析,获取注解参数。
38.如图3所示,注解解析器工作时,当某个持久层方法被执行时,注解解析器会先解析该方法的方法签名,分析出具体执行的是哪个类的哪个方法,如com.sztech.mapper.usermapper.listallusers(),表示com.sztech.mapper.usermapper类的listallusers方
法。
39.在获取到方法签名后,会提取方法上的注解信息,首先检查是否存在@datapermissions注解,该注解是一个组合注解,内部包含多个@datapermission注解,如果存在数据权限组合注解,则解析permissions参数,获取@datapermission注解子集;如果不存在@datapermissions注解,则解析@datapermission注解,该注解内部包含真正的权限表达式,参数包括columnname、valueconst和valueexpr。
40.注解解析器会找到方法上的每个@datapermission注解,并放到一个数组中,然后遍历该数组,对数组中的@datapermission注解实例进行解析,获取参数信息,并将最终结果封装成对象返回。
41.如图4所示,sql处理器的工作时,第一步是根据方法签名获取该方法对应的原始sql语句以及注解解析器的解析结果。
42.第二步,sql处理器将对注解参数进行计算,获取@datapermission注解的columnname参数,作为sql条件中运算符左边部分,获取valueconst或者valueexpr作为运算符右边部分,如columnname是user_name,valueconst为admin,则将组合成user_name=’admin’,valueconst或者valueexpr中存在多个值,则将=替换成in,这个过程由sql处理器内部自动判断。因为@datapermission注解可能会有多个,所以这个过程是通过遍历完成的。在计算完所有条件表达式后,sql处理器会使用innerexpression参数,将各表达式关联起来,innerexpression参数值通常为and或者or,形成sql子句。
43.第三步,在形成sql子句后,需要将子句与原始sql进行关联,如果原始sql中不存在条件子句(也就是没有where条件),则在sql子句前拼接where关键字,然后拼接到原始sql中;如果原始sql中存在条件子句,则将outerexpression拼接至sql子句前,然后拼接到原始sql中。
44.至此,带有数据权限控制的sql已经生成完成,接下来就是将sql提交给jdbc驱动执行。
45.注解组合通过@datapermissions注解来完成,上面已经提到过,@datapermissions注解是一个组合注解,内部有一个permissions属性,其对应的值是@datapermission注解数组,数组内的注解表达式通过innerexpression参数关联,最终根据注解信息生成一个sql字句。
46.注解解析器会对组合注解@datapermissions进行解析,发现其内部包含了两个@datapermission注解,第一个@datapermission注解中columnname是role_id,值valueexpr是一个动态参数“#userrole“;第二个@datapermission注解中collumnname是user_id,值valueconst是一个常量参数”001“,innerexpression和outerexpression都是and。注解解析器根据上述信息,将注解转换成最终的sql子句。
47.需要注意的是,本实施例中动态参数是一种会根据运行时的环境不同而动态调整的特殊参数类型,在一种基于注解的数据权限控制方法中,动态参数是一个以“#”开头的字符串,具体的值包括#usercode、#userrole、#username、#currentorg四种,分别表示当前登录人的用户编码、用户角色(列表)、用户名、用户所在机构(列表),动态参数的值会在用户登录时自动注入。
48.以上所述仅为本发明的优选实施例,并非因此即限制本发明的专利保护范围,凡
是运用本发明说明书及附图内容所作的等效结构变换,直接或间接运用在其他相关的技术领域,均同理包括在本发明的保护范围内。