Prepared statement是当前主流关系数据库都支持的一个功能,昆仑数据库系统也支持此功能。
今天我和大家讲讲使用prepared statement的好处。主要有两点,首先可以大大提升信息系统的安全性,防止SQL注入;还可以在一定程度提升查询性能。
所以强烈建议大家使用prepared statement功能。至于prepared statement的具体编程和API用法,本文不在此赘述,可以参考相关数据库的client API的文档。下面详细讲解prepared statement功能的这两个巨大的优势的工作原理。
Prepared statement为什么可以阻止SQL注入
SQL注入的原理
当前大多数信息系统都是用一个软件或者网页作为前端接收用户输入,然后在服务器的应用层(也就是使用java,php,python,CGI等开发的服务器应用软件系统)使用这些输入,实现应用逻辑,最终使用用户输入作为参数操作后台数据库做数据的增删改查。
很多应用开发者直接把前端用户的输入字符串作为SQL查询的一部分,拼接成一个SQL语句,这是一种非常差的编程方式。假如有一个系统,它的前端做一个删除产品的功能,它使用一个文本框接收用户输入一个产品编号,然后后端使用这个编号作为参数来删除产品。拼接SQL字符串的伪代码是
sqlstr = 'delete from products where pcode=\'' + textbox.string_value + '\'';
复制
此时如果用户在前端输入这样一个字符串 : xx‘ or ‘1,那么最终送给数据库的sql语句就是
delete from products where pcode=’xx’ or ’1‘;
复制
那么这个语句就会把系统products表的所有数据都删除。
通常这类问题中,如果用户输入参数作为数值等非字符串参数值使用,那么有一定编程经验的开发者会把用户输入转换为数值等所需类型的常量然后再做拼接,这样就可以避免上述注入。以上面的查询为例,如果pcode列是int类型,那么用户的这个输入:
xx‘ or ‘1
这个字符串经过数值转换,转为0,然后应用再做sql语句拼接,最终送给后端的sql语句就是
delete from products where pcode=0
这样虽然可能会误删另一行,但是至少不会丢失全表数据。但是一些小白开发者连上面的数值类型转换都不做,那么就无法在这种简单情况下避坑了。
而如果上例的pcode确实就是字符串类型,现在有一些应用层的工具和开发范例来避免SQL注入,比如禁止各种运算符字符(比如 +=-/|&等)或者禁止某些SQL关键字(比如select, or,and等),但是无法完全杜绝SQL注入。
可以说,只要用户输入的字符串仍然会直接被关系数据库的语法解析器来解析,那么SQL注入就一定是可以实现的。换个通俗点的说法:只要你还在应用层直接使用用用户输入的字符串(部分或者全部)来拼接SQL语句,那么SQL注入就一定会发生。
那么如何一劳永逸的避免SQL注入呢?这就要使用prepared statement。
Prepared statement的工作原理
以上面的sql语句为例,prepared statement就是
delete from products where pcode=?;
关系数据库的SQL解析器解析和优化这个语句,形成一个查询计划。在客户端用户程序得到的是这个prepared查询语句的一个句柄(handle),在session有效期内有效。这个查询计划就是执行这个查询语句的方法,但是在没有得到具体的参数之前,这个查询计划是无法执行的。
当用户通过其句柄(handle)绑定(bind)参数给这个prepared statement之后,用户就可以执行这个查询计划了。此时无论用户绑定什么样的参数,这个参数并不会被SQL解析器再次解析,它只是作为指定类型的参数值被这个查询计划使用来完成查询执行。所以,即时用户绑定的参数是
xx‘ or '1
那么最终相当于执行的SQL语句是
delete from products where pcode=‘xx\' or \'1';
这样就不会有任何数据损失的危险。
并且,用户可以多次反复绑定不同的参数给这个prepared statement,这样,假如这个结构的sql语句数量很大的话,数据库系统就避免了大量地解析和优化同一结构的SQL语句,从而提升系统性能。
推荐阅读
KunlunBase架构介绍
KunlunBase技术优势介绍
KunlunBase技术特点介绍
KunlunBase集群基本概念介绍
END
昆仑数据库是一个HTAP NewSQL分布式数据库管理系统,可以满足用户对海量关系数据的存储管理和利用的全方位需求。
应用开发者和DBA的使用昆仑数据库的体验与单机MySQL和单机PostgreSQL几乎完全相同,因为首先昆仑数据库支持PostgreSQL和MySQL双协议,支持标准SQL:2011的 DML 语法和功能以及PostgreSQL和MySQL对标准 SQL的扩展。同时,昆仑数据库集群支持水平弹性扩容,数据自动拆分,分布式事务处理和分布式查询处理,健壮的容错容灾能力,完善直观的监测分析告警能力,集群数据备份和恢复等 常用的DBA 数据管理和操作。所有这些功能无需任何应用系统侧的编码工作,也无需DBA人工介入,不停服不影响业务正常运行。
昆仑数据库具备全面的OLAP 数据分析能力,通过了TPC-H和TPC-DS标准测试集,可以实时分析最新的业务数据,帮助用户发掘出数据的价值。昆仑数据库支持公有云和私有云环境的部署,可以与docker,k8s等云基础设施无缝协作,可以轻松搭建云数据库服务。
请访问 http://www.kunlunbase.com/ 获取更多信息并且下载昆仑数据库软件、文档和资料。
KunlunBase项目已开源
【GitHub:】
https://github.com/zettadb
【Gitee:】
https://gitee.com/zettadb