【发布时间】:2010-11-04 08:01:37
【问题描述】:
是否有与 PHP 的 mysql_real_escape_string() 等效的 Java?
这是为了在将 SQL 注入尝试传递给 Statement.execute() 之前对其进行转义。
我知道我可以使用 PreparedStatement 代替,但我们假设这些是一次性语句,因此准备它们将导致 lower performance。我已经将代码更改为使用 PreparedStatement,但鉴于现有代码的结构方式,escape() 函数将使代码更改更易于查看和维护;我更喜欢易于维护的代码,除非有令人信服的理由导致额外的复杂性。此外,数据库对 PreparedStatements 的处理方式也有所不同,因此这可能会使我们暴露于数据库中以前从未遇到过的错误,需要在发布到生产环境之前进行更多测试。
Apache StringEscapeUtils escapeSQL() 只转义单引号。
后记: 我继承的环境中有很多微妙之处是我在我的问题中故意避免的。
需要考虑的两点:
1) 准备好的语句不是万能的,不能提供 100% 的 SQL 注入保护。一些数据库驱动程序使用不安全的字符串连接来实例化参数化查询,而不是将查询预编译为二进制形式。此外,如果您的 SQL 依赖于存储过程,则需要确保存储过程本身不会以不安全的方式构建查询。
2) 大多数准备好的语句实现将语句绑定到实例化该语句的数据库连接。如果你使用数据库连接池,你需要小心
仅将准备好的语句引用与准备它的连接一起使用。一些池化机制确实透明地实现了这一点。否则,您也可以合并准备好的语句,或者(最简单但开销更大)为每个查询创建一个新的准备好的语句。
【问题讨论】:
-
您更喜欢易于维护的代码,但您更愿意使用手动字符串转义而不是 PrearedStatement?
-
鉴于现有代码(我没有编写)的方式,是的,它会更容易维护。
-
较低的性能可能比安全风险更有吸引力。安全惩罚可能太高了。在应用程序初始化代码中准备好你的语句,惩罚可能不明显(当然取决于应用程序)。
标签: java sql mysql security jdbc