使用 StringBuilder 和 JPA 原生查询有什么风险?

What are the risks when using StringBuilder and JPA native queries?

我需要创建一个原生 sql 查询,我打算使用 StringBuilder 来创建它。

StringBuilder sqlQuery = new StringBuilder();
    sqlQuery.append("SELECT ");
    sqlQuery.append("b.\"id\", ");
    sqlQuery.append("b.\"title\", ");
    sqlQuery.append("a.\"author_name\" as author ");
    sqlQuery.append("FROM ");
    sqlQuery.append(":dbName b ");
    sqlQuery.append("JOIN ");
    sqlQuery.append(":dbName2 a");
    sqlQuery.append(" ON a.\"id\" = b.\"author\"");

    ObjectQuery query = objectManager.createQuery(sqlQuery.toString());
    query.setParameter("dbName", "Book");
    query.setParameter("dbName2", "Author");

使用StringBuilder的append安全吗?这不会导致攻击者注入 SQL 吗?攻击者是否能够附加将删除整个数据库的查询的一部分?有什么建议吗?

我知道这个查询很简单,可以写在一个字符串中,但我有更大的查询,使用 if 语句和循环,根据参数附加更多行

我知道命名查询更安全,但就我而言,直到最后一刻我才知道查询会是什么样子。

如果您在示例代码中使用 Query.setParameter() 设置参数值:

query.setParameter("dbName", "Book");
query.setParameter("dbName2", "Author");

你不应该有 SQL 注入问题。

SQL 注入发生在您将自己连接到创建的查询中的用户数据时。
但在这种情况下您不是,因为由 StringBuilder 对象创建的查询完全由您掌握,不会从外部客户端获取任何值。

Is it safe to use the append of StringBuilder?

虽然 StringBuilder 变量(注意:StringBuilder 不是线程安全的)是在方法范围内创建和操作的,但它并不比其他解决方案更安全或更不安全。

它与安全性没有任何关系,但正如@HRgiger 所建议的,一个好的替代方法是使用 Criteria API.
当您解释查询的构造非常动态时,这是有道理的:

I have much bigger query with if statements that decides what to append

它将产生更易于维护和可读的代码。

在这种情况下,没有受到 SQL 注入攻击的风险,仅仅是因为使用了 setParameter,但您必须注意 StringBuilder 不是线程安全类型。