使用休眠防止 SQL 注入

Posted

技术标签:

【中文标题】使用休眠防止 SQL 注入【英文标题】:SQL injection prevention with hibernate 【发布时间】:2013-05-24 07:55:43 【问题描述】:

我有一个现有代码,其中应用程序根据许多条件生成不同的 sql,并通过休眠会话 createSQLQuery() 执行它们。在这里,参数与驻留在 java 类中的 sql 字符串连接,作为正常的字符串替换。这里的问题是现在我需要防止 sql 注入。因此,为此我必须使用 getNamedQuery() 并绑定参数,以便 hibernate 处理特殊字符。但问题是将字符串 sql's 移动到 xml 文件是一种开销,因为有条件地生成 sql's。所以我决定手动进行特殊字符验证并将其附加到字符串查询并按现在的方式执行。 然后我检查了我发现的 PrepareStatement 的来源,它只是抛出了一个异常

byte[] arrayOfByte1 = new byte[0];
try

   arrayOfByte1 = CharsToBytes(this.OdbcApi.charSet, arrayOfChar);

   catch (UnsupportedEncodingException localUnsupportedEncodingException) 

在将参数与字符串查询连接以消除 sql 注入之前,如何在 java 类中对参数进行与上述相同的编码?或者有什么办法我仍然可以保留字符串sql,因为它是一个附加参数并使用hibernate来执行查询?

【问题讨论】:

【参考方案1】:

据我所知,您希望动态创建 SQL 查询,因为条件组合(我猜来自 UI)可能非常复杂。没关系。您需要控制的只是用户提供的参数。为此,您可以而且应该仍然使用 Hibernate 的createSqlQuery()。该函数理解? 的位置参数(从查询字符串的开头编号),或:param_name 语法,然后您提供命名参数。您无需将任何内容移动到 xml 文件中。

Section 16.1.7 有例子。

【讨论】:

谢谢安德鲁。它对我有很大帮助。在这里,我使用 createSQLQuery 并使用 setString() 方法绑定参数。我在其他地方看到它使用 getNamedQuery() 并使用 setParameterList() 方法附加参数。我希望两种方式都可以让hibernate处理sql注入,对吗? 简短回答:是的。这项工作并不是由 Hibernate 真正完成的,而是因为 Hibernate 本身为您的数据库调用了 JDBC 驱动程序(执行此操作的信息可能在persistence.xml 文件,尽管您的 IDE 可能有其他方法)。为了防止 SQL 注入,这些驱动程序已经非常小心。我相信 PreparedStatement 是安全的。无论如何,驱动程序编写者为此付出了更多的时间和精力,而不是作为一个更大项目的一部分。重新发明***作为编码练习是可以的,但在生产中通常不好。【参考方案2】:

如果您需要将自定义 SQL 组装到查询中,我发现编写自己的包含自定义 SQL 的条件类效果很好。

您只需要实现 Criterion 接口。 https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/criterion/Criterion.html

(另见 'not null' 的 Hibernate 实现:http://www.grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate/3.2.4.sp1/org/hibernate/criterion/NotNullExpression.java?av=f。)

然后,您可以使用普通的休眠条件 API 简单地构建每个自定义查询。

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html#querycriteria-creating

正确清理 SQL 值很痛苦 - 尽量避免它! ;-)

【讨论】:

以上是关于使用休眠防止 SQL 注入的主要内容,如果未能解决你的问题,请参考以下文章

休眠和 SQL 注入

ThinkPHP如何防止SQL注入?

Android中是怎样防止SQL注入的?

防止XSS注入的方法

MyBatis怎么防止SQL注入

PHP怎么防止sql注入