动态SQL及安全性(Birtvs润乾)

静态 SQL 与动态 SQL

对于题目中提到的动态 SQL,显然应该有一种静态 SQL 与之相对,那么两者应该怎么理解?我们先来个基本的认识。

在华蓥等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都做网站、网站制作 网站设计制作按需定制开发,公司网站建设,企业网站建设,品牌网站设计,网络营销推广,外贸网站制作,华蓥网站建设费用合理。

静态 SQL 之“静态”,意味着在执行之前就已经明确了该 sql 在数据库执行后的业务含义,也就是对于做啥事儿我们是清楚的,只不过需要知道这事儿的具体内容有哪些。比如“select userID,username from users where deptName=’销售部’”,意思就是查销售部的所有用户 ID 及用户名。 再稍微灵活一点,可以写作“select userID,username from users where deptName=?”,此时语句中的“?”传递哪个部门名称,相对应的就查哪个部门的用户信息。但,sql 本身所要做的“查询某部门下的用户信息”这个事情我们是完全明确的,不确定的只是用户有多少,各自的信息是什么。

而动态 SQL 之所以称为“动态”,就是在是否“明确业务含义”这一点上是“不明确”的,也就是说 sql 应该执行出啥结果,我们本身并没有明确的预期,包括查什么、用哪些条件以及怎么组合这些条件等——原则上,这些都可以随意选择组合。

比如:“select userID,userName from users where ${condition}”,此处的 condition 可以随意指定合理的查询条件,当传入“deptName=’xx 部门’”时,执行结果是查询某部门的用户信息;当传入“roleName=’技术主管’”时,则是按照角色筛选复合条件的用户信息。尽管都是返回用户信息,但不同条件下,我们可以认为是两个不同的业务,这里的 sql 我们就称之为是动态的,显然,这样的 sql 执行后得到的结果的业务含义也是完全不确定的。

上面动态 sql 的例子是条件不固定,实际上动态 sql 还允许返回字段不确定,如“select userID,${fields} from users where …”, 需要查询哪些字段,完全由动态指定的”fields”来确定,可以查 deptName,也可以查 userName 和 deptName,非常自由、灵活。

同理,使用的物理表也可能不固定,例如定义为“select … from ${table} where …”时,”table”给定啥值就从哪个表查数据。

结合两者的具体含义,可以分析得到各自的优劣所在:

l   静态 SQL :功能固定,比较传统,但相对比较安全。

l   动态 SQL :自由灵活,但同时不得不提到 sql 植入风险,一旦被攻击者利用可能的 sql 漏洞,会有相当严重的安全问题,如窃取用户信息、篡改数据等等。

而在常用的报表工具使用场景中,报表开发人员一般都没有 DBA 的功力,因此难以对 sql 的安全性问题考虑周全,动态 SQL 可能带来的风险也就很难排除。而要规避动态 SQL 风险,无非是下面两种方法:

1、   让 dba 配合工作,尽可能协助提供安全性高的 sql ;

2、   希望报表工具可以提供规避 sql 注入风险的方法。

方法 1 需要依赖外部 DBA 的配合,不是总能满足,所以,比较可行的,还是在考察报表产品时,考虑报表工具是否提供防 sql 植入风险的功能支持。不然,在安全第一的前提下,就只能不用动态 sql ,退而选择静态 sql 了,毕竟安全还是最重要的,一旦造成信息泄露,责任很难承担。

下面,我们就对比一下常见的两种报表工具, Birt 和润乾报表,看看它们各自在动态 SQL 以及安全性方面的表现如何:

Birt 动态 sql 实现

Birt 动态 sql**** 的做法有两种:

1、   数据集中通过 script 拼接 ****sql

2、   应用程序来实现:这个太麻烦,需要有 Java 开发能力,咱们就不介绍了,感兴趣的可以到网上搜索自行研究。

下面我们通过实例来讲解一下在数据集中通过 script 脚本拼接 sql 的方式。

注:例子以“员工表”为例,员工表内存放有“工资”及“应发工资”两个字段,我们通过动态 SQL 实现由终端用户选择应该查询“工资”列还是“应发工资”列

动态 SQL 及安全性(Birt vs 润乾)

1、 新建报表并新增数据源(hsql)

动态 SQL 及安全性(Birt vs 润乾)

2、   新增数据集

如,数据集名称为“ dt ” ,query text 为“select * from 员工”。实际这里可以定义为空,但为了保存等操作不报错,这里需要随便写个 sql。

动态 SQL 及安全性(Birt vs 润乾)

3、   利用 script ,在 data set 的 before open 事件中实现动态 sql

点击   dt   数据集,选中 script 页,选择 beforeOpen 并编辑如下

动态 SQL 及安全性(Birt vs 润乾)

脚本如下(含义为当 qField 传进来是“工资”时,拼入工资字段查数据,为“应发工资”时则对应查询,默认查询工资列):

var  query =  this .queryText; // 获取 query text 内定义的 sql

query = "";

query =“SELECT 编号, 部门, 姓名 , 性别, 出生日期, 入职日期, 籍贯,”;

var  queryField = params[“qField”].value;

if (queryField!= null &&queryField!=""){

query += queryField ;

}

else {

query +="工资" ; // 如果不给值或默认状态,查工资列

}

query += "as salary from 员工表";

this .queryText = query;

4、   报表模板设计

动态 SQL 及安全性(Birt vs 润乾)

前面 6 列为常规列,拖拽字段到 dataRow 即可,第 7 列位动态列,这里当根据传入参数的不同,显示不同的标题(header row)及数值(data row),其中

Header row 表达式为:params[“qField”]

动态 SQL 及安全性(Birt vs 润乾)

Data row 表达式为:dataSetRow[params[“qField”]]

动态 SQL 及安全性(Birt vs 润乾)

5、   结果展现

(1)   当输入 qField 参数为“应发工资”时

动态 SQL 及安全性(Birt vs 润乾)

结果

动态 SQL 及安全性(Birt vs 润乾)

(2)   当输入 qField 参数为“工资”时

动态 SQL 及安全性(Birt vs 润乾)

结果

动态 SQL 及安全性(Birt vs 润乾)

分析小结

暂且不考虑上述操作涉及的复杂的制作过程,即便辛苦做出了效果,我们也不难发现其中留有很大漏洞,那就是这种拼串的方法很容易出现 sql 植入问题。

比如,当攻击者尝试给 qFiled 参数传入“身份证号”,而恰好又存在该字段的话,用户的身份证号信息就全部暴露了,同样,用类似的方法还可以猜到“电话号码”、“家庭住址”,等等等等,这些敏感信息的全面泄露,意味着安全保障的不堪一击。

而针对脚本这种做法,想要全面规避风险非常麻烦,可能的方式是在脚本里加入大量的判断,尽力排除所有 “身份证”、“电话号码”、“手机号码”等各种情况。对于一两个报表这么搞还行,多了肯定就费劲了,并且后期维护也得蒙圈。

润乾报表动态 sql 实现

同样以“员工表”为例,员工表内存放有“工资”及“应发工资”,我们来实现由终端用户选择应该查询“工资”列还是“应发工资”列。

润乾报表采用动态参数实现:

(1)   连接 demo 数据源

(2)   用向导生成报表

通过向导,一步生成如下网格式报表模板

动态 SQL 及安全性(Birt vs 润乾)

(3)   修改数据集,增加动态列

A、   增加报表参数“ qFiled ”

动态 SQL 及安全性(Birt vs 润乾)

B、   数据集 sql 中增加动态列

采用宏的方式引入, sql 改为如下

动态 SQL 及安全性(Birt vs 润乾)

(4)   修改报表模板,增加动态列

动态 SQL 及安全性(Birt vs 润乾)

G1:=@qFiled

G2:=ds1.${qFiled}

(5)   效果展示

A、   qFiled 传入“应发工资”

动态 SQL 及安全性(Birt vs 润乾)

结果

动态 SQL 及安全性(Birt vs 润乾)

B、   qFiled 传入“工资”

动态 SQL 及安全性(Birt vs 润乾)

结果

动态 SQL 及安全性(Birt vs 润乾)

分析小结

很显然,仅从做法而言,润乾报表就比 birt 要简单的多,不需要写任何脚本即可实现,对开发人员的技术要求也不高,对应后期维护也就很轻松了。

当然这里也存在 sql 植入的风险,但是润乾报表作为一款商业软件,厂商已经为用户考虑到了,可以通过专门的配置规避风险,具体使用也很简单,但功能很强大。

关于 sql 植入及报表规避的有专门的文章做详细的介绍,可参考《报表的 SQL 植入风险及规避方法》 url :   报表的 SQL 植入风险及规避方法

总结

不管是开源还是商业报表,可能对于某功能的实现都没什么问题,但制作方法的简便性、考虑问题是否周全(比如安全性问题)等方面的差距就可能会非常明晰。

开源报表固然有它的优点——不用花钱!!! 但工作量相对要大很多,服务或支持也没有保障,只能靠用户自己埋头苦干去研究了。而商业报表则是一条捷径,虽然要花一点点 Money,但考虑到效率及安全性方面,那就真是完全可忽略的成本了。

详情链接: http://c.raqsoft.com.cn/article/1564367236761?r=gxy


文章标题:动态SQL及安全性(Birtvs润乾)
文章出自:http://scyanting.com/article/pjeics.html