5

在 Java 中将变量插入数据库之前转义变量的推荐方法是什么?

据我了解,我可以使用 PreparedStatement.setString() 来转义数据,但是如果我不打算再次运行相同的查询,PreparedStatement 似乎有些不切实际。有没有更好的方法可以在不准备每个查询的情况下做到这一点?

4

5 回答 5

27

是的,对所有事情都使用准备好的语句。

  1. 它们被解析一次。

  2. 它们不受 SQL 注入攻击的影响。

  3. 它们是更好的设计,因为您必须考虑您的 SQL 及其使用方式。

如果您认为它们只使用一次,那么您就没有看到大局。总有一天,您的数据或您的应用程序会发生变化。


编辑。

为什么准备好的语句会让你想到你的 SQL?

  • 当你组装一个字符串(或简单地执行一个文本块)时,你并没有创建一个新PreparedStatement对象。您只是在执行 SQL——它可以非常随意地完成。

  • 当您必须创建(和保存) aPreparedStatement时,您必须稍微考虑一下封装和责任分配。语句的准备是在进行任何 SQL 处理之前的有状态事件。

额外的工作很小,但并非微不足道。这就是人们开始考虑 ORM 和数据缓存层的原因,以及类似的东西来优化他们的数据库访问。

使用准备好的语句,数据库访问不那么随意,更有意。

于 2008-12-28T22:21:58.030 回答
9

您永远不应该使用字符串连接自己构造 SQL 查询。在构建 SQL 查询时,您永远不应该手动转义变量/用户数据。所需的实际转义取决于您的底层数据库,并且在某些时候有人会忘记转义。

关键是:使用准备好的语句,不可能创建 SQL 可注入语句。通过自定义转义,这是可能的。选择是显而易见的。

于 2008-12-28T22:37:03.930 回答
4

准备一份声明并不那么昂贵。它比大多数替代品更安全。

于 2008-12-28T22:21:06.833 回答
3

我听说 PreparedStatement 比普通的 Statement 花费了一些额外的开销,如果我没有将用户输入连接到我的查询中,它应该是安全的。这可能是真的,但额外的成本并没有那么多,而且 SQL 查询会随着时间而变化。如果您今天开始使用 Statement 是因为您已经向自己证明了您的查询是防注入的,那么您将在维护程序员更改 SQL 以接受用户输入但不接受用户输入的那一天为失败做好准备考虑将该语句更改为 PreparedStatement。我的建议是始终使用 PreparedStatement 来避免麻烦,然后才能找到您。

于 2008-12-29T02:04:11.017 回答
3

Even better, don't use the JDBC API directly, because it's so error-prone (e.g. failing to properly clean up all resources in all cases). Use a JDBC helper object such as Spring's JdbcOperations interface, which considerably reduces the size and bugginess of your code. If you only use Spring for this one feature, you've still done yourself a massive favour compared to using the JDBC API directly.

于 2008-12-29T03:33:10.197 回答