是否有Java等价于PHP的mysql_real_escape_string()?
这是为了避免在将SQL注入尝试传递给Statement.execute()之前进行尝试。
我知道我可以改用PreparedStatement,但让我们假设这些只是一次声明,所以准备它们会导致性能降低。我已经将代码更改为使用PreparedStatement,但是考虑到现有代码的结构方式,escape()函数将使代码更改更易于查看和维护。我更喜欢易于维护的代码,除非有令人信服的理由说明其额外的复杂性。此外,数据库对PreparedStatement的处理方式也有所不同,因此这可能使我们面临以前从未遇到过的数据库错误,因此在发布到生产环境之前需要进行更多测试。
Apache StringEscapeUtils escapeSQL()仅对单引号进行转义。
后记:我继承的环境中有很多微妙之处,是我在问题中特意避免的。
需要考虑两点:
1)预备语句不是万能药,并且不能提供100%防止SQL注入的保护。一些数据库驱动程序使用不安全的字符串连接实例化参数化查询,而不是将查询预编译为二进制形式。另外,如果您的SQL依赖于存储过程,则需要确保存储过程本身不会以不安全的方式构建查询。
2)大多数准备好的语句实现将语句绑定到实例化该语句的数据库连接。如果您正在使用数据库连接池,则需要注意, 仅将预准备的语句引用与预准备的连接一起使用。一些池化机制确实透明地实现了这一点。否则,您也可以合并准备好的语句,或者(最简单但更麻烦的方法)为每个查询创建一个新的准备好的语句。
据我所知,没有“标准”的方式来做到这一点。
尽管您当前担心,但我强烈建议您使用准备好的语句。对性能的影响将是微不足道的-我们有一个类似的情况,每秒有数千条语句-其中大多数也是单发的。
您获得的安全性应比尚未出现的性能问题高得多。我认为这是“不要过早优化”的明确情况。
无论如何,如果您以后真的要发现性能问题,请仔细分析以确保准备好的语句是真正的原因,然后寻找替代方法。到那时为止,您应该省去尝试正确进行转义的麻烦。
当我推断您正在开发某种面向公众的网站时,这一点甚至更为重要-内部应用程序很少会获得足够的流量来关注性能。