防止SQL注入没有准备好的语句(JDBC)(Preventing SQL injection wit

2019-06-28 06:07发布

我有一个在一段时间插入可变数量的日志行到数据库中每一次数据库日志的appender。

我想,以防止SQL注入的方式来创建一个SQL语句,但不使用服务器端预处理语句(因为我在每一个变量数列的选择,其缓存不会帮助,但可能在这里会降低性能) 。

我也喜欢准备statments的便利性,以及他们喜欢串concatination。 有什么样一个“准备好的语句客户端”?

Answer 1:

这听起来像你没有基准最简单的办法 - 预处理语句。 你说他们“可能会伤害表现”,但要等到测试过它,你当然不会知道。

肯定会先测试准备语句。 即使他们稍有阻碍性能,直到你测试过他们,你将不知道你是否仍然可以达到您所需要的性能。

为什么要花费时间去寻找替代方案,当你还没有尝试过的最明显的一个?

如果您发现准备好的语句的执行计划缓存昂贵的,你可能会发现有调整或禁用的特定DB-方式。



Answer 2:

不知道如果我正确地理解你的问题。 有什么在PreparedStatement是不适合您的需求呢?

我认为,是否被缓存在服务器端的语句是数据库驱动程序和您正在使用的特定数据库的实现细节; 如果随着时间的推移查询/修改声明比这个应该没有影响 - 缓存/根本不会使用汇编语句。



Answer 3:

首先,Jon的回答,你应该最明显的解决方案,直到去表现测量是一个问题肯定是一般正确的方法。

我不认为你的表现担忧是错误的。 我已经看到一定预编译的复杂语句的性能显着规模的失败(在MS-SQL 2000)。 原因是该声明是如此复杂,它必须依赖于参数几个潜在的执行路径,但编译锁定一个在一组参数,而下一组的参数是太慢了,而重新编译会强制进行重新计算执行计划更适合于该组不同的参数。

但是,值得关注的是非常牵强,直到你在实践中看到它。

这里的根本问题是参数转义特定的数据库,所以除非JDBC驱动程序的数据库,是给你一些非标准做到这一点(可能性很小),你将必须有一个不同的库或不同的逃逸机制是非常具体的这一个数据库。

从你的问题的措辞,这听起来并不像你的性能问题还没有来meriting发现(或开发)这种解决方案的地步。

还应当指出的是,尽管JDBC驱动程序可能不是所有的行为这种方式,在技术上根据预编译应该在PreparedStatement对象缓存的规格,如果你把那个路程,每次都获得一个新的预处理,它不应该实际上缓存任何东西,因此整个问题可能是静音和需要追究特定JDBC驱动程序。

从规格:

带或不带IN参数的SQL语句可以被预编译并存储在PreparedStatement对象。 然后,该对象可用于有效地多次执行该语句。



Answer 4:

什么是错的使用,例如以下伪正规准备好的声明:

DatabaseConnection connection;
PreparedStatement insertStatement = ...;

    ...

connection.beginTransaction();
for (Item item : items)
{
   insertStatement.setParameter(1, item);
   insertStatement.execute();
}
connection.commitTransaction();

智能数据库实现会批量几个插入到一个通信交换瓦特/数据库服务器。



Answer 5:

我想不出理由,为什么你不应该使用准备好的语句。 如果您在J2EE服务器上使用连接池的服务器让您连接打开运行此,服务器缓存您访问/执行计划。 这不是数据缓存!

如果你每次都关闭的连接,那么你很可能不会获得任何性能。 但是,你仍然可以获得SQL注入预防

大多数Java性能优化的书会告诉你相同的: Java性能优化



Answer 6:

预处理语句不关心客户端或服务器端。

使用它们,丢弃任何SQL字符串连接。 没有一个单一的原因,不使用预处理语句。



文章来源: Preventing SQL injection without prepared statements (JDBC)