SDBatis:基于MyBatis和CBAC的数据库应用访问控制

2022-03-04 06:47叶茂林余发江
武汉大学学报(理学版) 2022年1期
关键词:访问控制视图语句

叶茂林,余发江

空天信息安全与可信计算教育部重点实验室,武汉大学国家网络安全学院,湖北 武汉 430072

0 引言

目前的大部分应用都将应用用户的身份认证信息、权限信息以及敏感资料都存储在数据库中。在这种情况下,要实现对应用的访问控制,一般可以使用的方法有两种:一种是使用数据库本身的访问控制机制,另一种是在应用层实现访问控制。使用数据库本身的访问控制机制最大的缺陷在于数据库连接池的广泛使用使得DBMS(database management system)无法确定当前应用用户。而在应用层实现控制的方式分为硬编码和使用安全框架两种,硬编码的方式依赖开发人员的编码能力,难以保证应用的安全性,使用安全框架可以提高安全性,但访问控制功能的开发与数据库、业务代码、安全框架都有关联,因此仍然存在开发繁琐、维护困难等问题。

Eykholt等[1]开 发 了SafeD,使 用 幻 影 提 取(phantom extraction)技术来强制执行符合访问控制策略的SQL语句,避免了使用数据库视图,使得广泛存在的视图更新问题得到解决。SafeD通过扩展JDBC的方式实现,文献[1]在Mysql和PostgreSQL上进行了实验,SafeD的效率和可用性良好。Mehta等[2]开发了一个既不依赖应用程序正确性,也不依赖特定的数据库支持的访问控制系统Qpala。Qpa⁃la在数据库适配器中实现。SafeD和Qpala都是基于传统的RBAC(role-based access control,基于角色的访问控制)开发的,而RBAC无法满足日益复杂的应用场景需求。并且SafeD和Qpala在数据库与应用层的中间层实现,如JDBC驱动。但不同种类的数据库JDBC驱动不同,扩展JDBC时需要对每个JDBC驱动进行更改。

针对以上问题,本文提出了一种新的访问控制解决方案SDBatis。SDBatis以CBAC(contextbased access control,基于上下文的访问控制)作为访问控制模型[3,4],同时解决了应用访问控制方式中开发繁琐、维护困难的问题。相对于以往的工作,SDBatis对复杂的应用场景和不同的数据库具有更强的适应性。

1 研究背景

1.1 数据库访问控制

应用的访问控制可以利用数据库自身的访问控制系统来实现,目前流行的数据库普遍支持创建和管理数据库用户,My SQL 8.0和Oracle还支持定义数据库角色[5],使用这两个功能可以完成表、列、视图、存储过程级别的访问控制[6]。使用角色进行访问控制的示例为:

GRANT SELECT(emp_id)ON employee TO manager

上述示例的含义是将查询employee表中emp_id列的权限赋予manager。本文给出的示例使用了一个虚拟的企业数据库,其中包括两张表,分别 为 职 员 表:employee(emp_id,name,gender,dept),职 员 工 资 表:emp_salary(emp_id,salary)。职员表包含职员的基本信息,职员工资表包含职员id和职员工资信息。

使用数据库访问控制机制的优势在于可以进行细粒度的访问控制(fine grained access control,FGAC),常见的方式为使用视图控制权限。如图1所示,CREATE VIEW语句表示创造一个包含职员名称和工资的视图;GRANT语句表示如果将查询该视图的权限赋予manager角色,则manager角色只能查询测试部门职员的名称与工资信息。但是使用视图的方式会面临一个新问题:视图更新问题[7,8]。一些数据库开发商为了细粒度访问控制开发了自己的系统,如Oracle 11g中实现的VPD(vir⁃tual private database,虚拟专用数据库)机制。VPD可以支持细粒度的访问控制[9,10],它通过当前数据库用户的“应用上下文”和VPD策略重写用户的SQL语句,以强制执行行级或列级安全性要求[11,12]。

图1 使用视图控制权限Fig.1 Use view control permissions

以上的访问控制方式都需要以连接数据库的用户作为目标或条件,但目前普遍采用数据库连接池来解决资源问题[13,14]。在使用连接池的情况下,开发者会配置权限较大的数据库用户来连接数据库,一个数据库用户会对应多个应用用户。比如在Piwigo11.5.0的test_piwigo.php中[15],root用户被配置为数据库连接用户,在应用运行时,root用户对应的是所有的应用用户。在这种情况下,DBMS就没有办法确定当前的应用用户,因此单纯使用数据库本身的访问控制机制来实现应用的访问控制难以实现。

SDBatis基于MyBatis实现,不依靠数据库访问控制机制,避免了连接池带来的问题,同时其具有对数据库进行较细粒度的行级访问控制的能力。

1.2 应用层访问控制

在应用层实现访问控制的方式分为两种:一种是开发人员自己在代码中嵌入判断语句;另一种是使用安全框架。在Piwigo中,开发人员采用的是嵌入判断语句的方式。如图2所示,在Piwigo 11.5.0的group_perm.php文件中,falsify代表改动状态,cat_true代表当前类别的选中状态,开发人员对请求中这两个参数进行判断,符合条件才定义SQL语句并执行。嵌入代码的方式对开发人员有较高的安全技术要求,并且在访问控制策略较为复杂时,访问控制相关的代码开发会非常繁琐且难以维护。另外,安全性上,开发过程中出现漏洞几乎是不可避免的。

图2 Piwigo访问控制代码示例Fig.2 Piwigo access control code example

安全框架的典型是Apache Shiro[16]。安全框架根据会话中用户的身份信息和设定的访问控制策略来判断当前请求是否符合访问控制策略。若不符合,会拦截资源请求。我们在RuoYi 4.6.1的us⁃er.html文件中找到了一个使用Shiro进行按钮访问控制的示例[17]。应用用户向服务端请求显示按钮时,由于此按钮配置了shiro:hasPermission="sys⁃tem:user:add"语 句,Shiro将 会拦截该请求并在Realm类中寻找权限信息。如图3所示,该函数在会话管理器中读取当前会话中的应用用户,根据用户id通过持久层框架MyBatis在数据库中查找角色和权限信息[18],然后将其添加在info中并返回给授权器。授权器将当前用户的权限信息与按钮需要的"system:user:add"权限进行比较以决定按钮是否显示。

图3 RuoYi中Shiro流程示例Fig.3 Shiro process example in RuoYi

但在使用安全框架实现应用访问控制的方式中,开发人员需要完成的工作包括制定策略、实现策略和权限判断。开发人员首先需要制定策略,然后将用户、角色、权限及其关系定义在数据库的表中以实现策略,最后在访问敏感资源处添加安全相关代码,在安全框架中配置权限信息的获取方式以实现权限判断。这会导致整个访问控制功能与数据库、业务代码、安全框架都有关联。由于安全相关代码分布在各处,因此依然存在开发繁琐、维护困难等问题。

本文提出的SDBatis避免了上述问题,在SDBatis中只需要配置访问控制策略和获取当前应用用户上下文属性就能够完成访问控制工作,使得开发和维护更为简便。

2 SDBatis设计

SDBatis的目标包括:

1)基于持久层框架实现,在保证访问控制功能模块独立的前提下,能够兼容不同的数据库,能够更准确和方便地获取应用用户上下文信息;应用SDBatis时只需在持久层制定访问控制策略、配置获取当前应用用户上下文属性就能够完成访问控制工作,不再需要在业务代码、安全框架等处编写访问控制相关代码,也不再需要在数据库中使用权限表格,减小应用访问控制功能开发和维护的成本。

2)使用CBAC作为访问控制模型,相比于传统的RBAC,更适用于动态系统,能实现更加灵活的访问控制。

3)支持对数据库的行级访问控制,能够确保应用用户无法访问数据库中超出其权限的行,从而最大程度地保证数据库中的数据不会被越权访问。

2.1 结构设计

为实现上述目标,我们将SDBatis设计为如图4所示的结构,主要包括SDBatis判断器、访问控制策略文件和SDBatis重写器等。在业务逻辑需要与数据库进行交互时,SDBatis将拦截所有经过MyBatis的SQL语句相关对象,读取访问控制策略和应用当前用户上下文信息,判断当前应用用户的上下文是否满足访问控制策略,然后根据判断结果交给SDBatis重写器进行重写,最后将SQL语句相关对象交还给MyBatis继续执行。

图4 SDBatis结构Fig.4 SDBatis structure

2.2 访问控制策略定义

SDBatis的访问控制策略以基于上下文的访问控制为基础。在基于上下文的访问控制中,主体和请求的上下文是评估一个访问请求的依据。我们借鉴了Shebaro等[19]描述在移动设备中基于上下文的访问控制模型的方法,并根据SDBatis的应用场景做出了一些调整,策略定义如下:

定义1单个上下文属性:CONTEXT=[CONTEXT_TYPE,CONTEXT_VALUE]。其中,CONTEXT_TYPE为上下文的类型,CONTEXT_VALUE代表上下文的值。

定义2上下文组c由多个CONTEXT组成:c=[CONTEXT 1,CONTEXT 2,CONTEXT 3,…]。

定义3访问请求r=,其中s∈Sub⁃ject,为 应 用 用 户;o=[TABLE_NAME,ROW_VALUE,COLUMN_NAME]∈Object,代表访问目标,为数据库中表的行与列其中ROW_VALUE和COLUMN_NAME允许为“*”,代表任意行或列;a代表动作组,a=[Action1,Action2,…],Action代表动作,即为对数据库中的条目进行的操作,Action∈{“SELECT”,“INSERT”,“UPDATE”,“DE⁃LETE”}。

定义4访问控制策略p=,其中r=[s,[TABLE_NAME,ROW_VALUE,COLUMN_NAME],a],c=[[CONTEXT_TYPE1,CON⁃TEXT_VALUE1],[CONTEXT_TYPE2,CON⁃TEXT_VALUE2]]。

2.3 访问控制策略类型

根据上下文类型的不同,SDBatis中的访问控制策略可以分为三类:环境策略、动态行策略、连接策略。

环境策略:访问环境指用户发出请求时所拥有的上下文属性,如设备信息、IP地址、访问时间等。策略p1表示一条只允许用户在早上9点到晚上7点之间对职员的工资信息进行任何操作的策略,p1属于限制访问emp_salary表的策略。SDBatis中定义的时间格式为:“YY-MM-DD-hh:mm:ss”,其中YY代表年份,MM代表月份,DD代表日,hh代表小时,mm代表分钟,ss代表秒。那么p1的形式化表示如下

动态行策略:SDBatis能够完成行级的访问控制,即限制应用只能访问数据库中的哪一行或哪些行。在实际的应用中,行策略往往需要根据当前用户的上下文而变化,如不同职员的职员id不同,策略限制其能够访问的数据库表中的行也不同。SDBatis支持这样的动态表示。我们采用与MyBatis中表达动态变量类似的语法来表示这样的策略属性,如在策略p2中使用了#{emp Id}表示当前职员的id。策略p2表示职员只能查询自己的工资信息,即只能查询在emp_salary表中emp_id与自己的职员id对应的一行。p2的形式化表示如下

连接策略:在实际应用中,SQL语句中往往会出现多表联合查询的情况,这种情况下策略依然以行策略的方式表示,但在判断和重写阶段,SDBatis会分析当前SQL语句中涉及的所有表以及策略中对应的限制条件。

3 SDBatis实现

3.1 策略实现

在SDBatis中,访问控制策略使用xml文件存储,以基于上下文的访问控制规则制定,角色、环境都被视为上下文属性。xml文件的大致结构为:在根节点下包含若干个节点,代表当前用户的角色上下文;每一个role的策略分为读写两种,使用标签表示;读写策略再细分为各个表的策略,每一个

标签代表一张表,而
标签内的每个标签代表一条限制条件,其中定义了具体的限制条件类型、限制值等。

3.2 功能实现

SDBatis主要在MyBatis的基础上增加了3个文件:sdbatis-strategy.xml、SDBatisInterceptor.java和SDBatisUtils.java。其中,sdbatis-strategy.xml为访问控制策略文件;SDBatisInterceptor.java为SDBatis主体文件,SDBatis判断器、重写器都包含在这个文件中;SDBatisUtils.java中储存工具函数。

MyBatis插件机制为拦截SQL语句相关的对象和对它们进行操作提供了接口,SDBatis拦截器拦截MyBatis的Executor类中的query和update函数,在这两个函数执行前拦截器会读取函数变量。在MyBatis中,SELECT语句的处理将会调用query函数,而DELETE、UPDATE、INSERT语句的处理会调用update函数,所以query和update变量中包含了该次调用对数据库的请求的具体参数。获取到参数后,SDBatis从应用层获得当前应用用户上下文信息,然后读取访问控制策略文件,根据用户上下文、访问控制策略、SQL语句进行判断,如果当前执行的对象与访问控制策略不相关,则不进行处理;如果相关,SDBatis会重写变量,使变量符合访问控制策略中的限制,从而确保发送给数据库的SQL语句不会超出当前用户的权限,达到对数据库的行的访问控制的目的。最后,SDBatis用重写后的变量替换函数中原来的变量,剩余的执行过程交回给My Batis。SDBatis判断器和重写方法是SDBatis中的两个重要组成部分,下面对它们进行描述。

SDBatis判断器:判断器的主要功能是判断当前执行的SQL语句相关对象与访问控制策略是否相关。这个过程需要读取访问控制策略文件和解析SQL语句。dom4j是一个处理xml文件的工具[20],它解决了访问控制策略文件的读取和解析问题;JSqlParser是一个常用的解析SQL语句的工具[21],但由于其效率较差,我们只用它对SQL语句进行了简单的分析,提取SQL语句中包含的表名、WHERE语句表。后续的判断中,首先根据表名称找到限制条件,再将限制条件与当前用户上下文进行对比,如果没有对应的限制条件或满足限制条件则不做处理;若不满足限制条件,则根据限制条件的种类将当前的请求置为空或重写当前SQL语句相关对象。

重写方法:在MyBatis中对SQL语句进行重写并不能通过简单地替换SQL语句中的字符串完成。在MyBatis的设计里,SQL语句支持动态变量,MyBatis插件的功能局限性使得SDBatis拦截器无法直接拦截到最终执行的SQL语句,而只能获取到未填写变量的SQL语句和变量对象。我们研究了这些对象,设计了替换和添加两种方式来完成对不同SQL语句的重写功能。若WHERE语句中已经包含限制类型但值与策略不符时使用替换的方法,替换指使用访问控制策略中规定的值替换当前参数中的变量;若WHERE语句中不包含限制类型,需要重写时,在未填写变量的SQL语句后添加AND语句,如此也能完成对SQL语句的访问限制。在该过程中有一个特例,INSERT语句不包含WHERE子句,因此处理方式与其他语句不同。我们对INSERT语句的处理方式相对简单,只需要判断当前用户上下文是否满足对当前SQL语句中相关表的插入要求,若有,则允许插入;若没有,则禁止插入。

4 实验与分析

4.1 实验方案

SDBatis支持以MyBatis作为持久层框架的应用。实验中,我们选择了在github上拥有1.1k Star的RuoYi作为实验对象,实现了SDBatis的一个原型。基于RuoYi项目的基本业务逻辑,策略文件中的测试访问控制策略配置如表1所示。

表1 测试访问控制策略配置Table 1 Test security access control policy configuration

以未使用SDBatis的RuoYi应用执行的请求为基准(base),根据设定的访问控制策略和RuoYi的业务逻辑,我们制定了3组对照实验。第1组实验将使用硬编码和SDBatis进行权限控制的方法和基准值进行比较,其中测试硬编码方法时对RuoYi源代码进行了人工分析和简单修改。第2组实验中请求被分为6类,每一类请求的类型和描述如表2中所示,该组实验主要测试了SDBatis在各类访问控制条件下的表现。第3组实验重点测试行策略请求,请求共分为3类,包括简单行策略请求、嵌套查询请求、连接策略请求等,3类请求分别在RuoYi原生和使用SDBatis之后两种场景下测试。

表2 测试请求Table 2 Test request

实验测试的环境为:Inter Xeon E3-1230 V 2 3.3 GHz CPU,16 GB RAM,256 GB SSD,WINDOWS 10操作系统,IntelliJIDEA开发工具,RuoYi 4.6.2。实验测试分为功能测试和性能测试两部分。功能测试指对SDBatis能否完成预期功能的测试,测试的主要方法为人工检验请求的测试结果与预期结果是否匹配;性能测试指测试每一类请求运行的时间,对比各种情况下运行时间的差异,从而研究SDBatis对应用运行效率的影响。

执行测试请求时,每一类测试分别执行100次并计算平均时间,每次执行时使用SpringBoot中的StopWatch工具对程序运行时间进行记录和计算[22]。

4.2 结果与分析

实验结果分为功能测试结果和性能测试结果两部分。在3组实验的功能测试中,SDBatis成功达到了对时间策略、IP策略、动态行策略请求处理的预期。我们人工分析了RuoYi本身的访问控制方法,并将SDBatis与其进行比较,得到如表3中所示的结果。结果表明使用SDBatis后只需要配置访问控制策略文件即可完成权限判断,降低了访问控制功能开发的成本,且SDBatis支持行级访问控制,比RuoYi原生的访问控制方式更加灵活。

表3 访问控制功能比较Table 3 Compar ison of access contr ol functions

第1组实验的性能测试结果如表4所示,结果表明,相比于RuoYi使用安全框架进行访问控制的方式,使用硬编码所需时间减少了约7%,而使用SDBatis的方式增加了约20%的时间。第2组实验的性能测试结果如图5,time1和time2分别代表满足和不满足访问控制策略的时间相关请求,IP1和IP2分别代表满足和不满足访问控制策略的IP相关请求,row代表动态行策略请求。使用SDBatis后,时间策略和IP地址策略相关请求的运行时间增加了约20%,而行策略请求运行时间增加了34%。行策略请求运行时间更长,这可能是因为在处理行策略请求中需要对SQL语句进行分析和重写。

图5 各类策略请求测试运行时间Fig.5 Various types of strategy request test run time

表4 不同访问控制方式耗时Table 4 Running time of different access control ways

图6显示了第3组实验的性能测试结果,在RuoYi原生访问控制下,请求的执行时间变化较小,而在使用SDBatis后,嵌套查询请求和连接策略请求会分别多花费6%和8%的时间,原因可能是这两类请求的SQL语句更为复杂,所需的分析时间更长。综合3组实验结果,我们发现SDBatis对应用性能有一定的影响,但在SDBatis带来的优势下,这种程度的性能影响是可以接受的。

图6 行策略请求测试运行时间Fig.6 Row strategy request test run time

5 结语

本文提出了一种新的对应用的访问控制解决方案:SDBatis。相比于以往的访问控制系统,SDBatis可以让开发人员在持久层中完成访问控制工作,降低了访问控制功能开发的成本。另外,SDBatis基于CBAC和MyBatis插件模型开发,与前人研究开发的SafeD和Qpala相比,SDBatis中以CBAC的访问控制模型为基础,环境策略和动态行策略使其能够适应日益复杂的访问环境,而基于MyBatis开发的理念使其能被各类使用MyBatis作为持久层框架的应用使用。在实际应用中,SDBatis带来的延迟也是可以接受的。未来,我们希望能设计出兼容性更高、适用性更广、使用门槛更低的访问控制系统,SDBatis只是一次初步的尝试。在SDBatis中,持久层框架MyBatis是基础,而未来的研究将不限于单一的框架。最后,SDBatis在处理SQL语句和策略文件时的效率还有待提高,对于复杂SQL语句的判断和重写仍需进一步完善。

猜你喜欢
访问控制视图语句
云的访问控制研究
Y—20重型运输机多视图
SA2型76毫米车载高炮多视图
《投影与视图》单元测试题
云计算访问控制技术研究综述
Django 框架中通用类视图的用法
基本算法语句
我喜欢
作文语句实录
校园骨干层网络交换机的访问控制技术