如何使用 JPA 防止本机插入查询中的 SQL 注入?
How to prevent SQL injection in native insert query with JPA?
我正在使用 JPA/Hibernate 的本机查询在 PostgreSQL 上执行插入或更新 ("upsert"),具体取决于对象是否存在。代码如下所示:
val values: String = items.joinToString(", ", transform = this::convertItemToSqlValue)
val query = """
insert into item (field1, field2)
values $values
on conflict on constraint item_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
entityManager.createNativeQuery(query).executeUpdate()
函数 convertItemToSqlValue
创建一个形式为 ('value a', 123)
的字符串。
位置参数 (values ?
) 无效(并导致语法错误)。
如何防止 SQL 使用这种语句进行注入?
根据用户输入动态构建 SQL 语句并不是最好的主意。最好使用准备好的语句。但是,在这种情况下,似乎没有一种简单的方法可以使用 JPA EntityManager 执行补丁更新。
可以使用 JDBC 设置多个值。以下示例显示 Spring's JdbcTemplate:
的用法
val items: List<Item> = ...
val statement =
"""
insert into item (field1, field2)
values (?,?)
on conflict on constraint arbeit_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
jdbcTemplate.batchUpdate(
statement,
object : BatchPreparedStatementSetter {
override fun setValues(statement: PreparedStatement, index: Int) {
val item = items[index]
statement.setString(1, item.field1)
statement.setInt(2, item.field2)
}
override fun getBatchSize(): Int = items.size
}
)
我正在使用 JPA/Hibernate 的本机查询在 PostgreSQL 上执行插入或更新 ("upsert"),具体取决于对象是否存在。代码如下所示:
val values: String = items.joinToString(", ", transform = this::convertItemToSqlValue)
val query = """
insert into item (field1, field2)
values $values
on conflict on constraint item_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
entityManager.createNativeQuery(query).executeUpdate()
函数 convertItemToSqlValue
创建一个形式为 ('value a', 123)
的字符串。
位置参数 (values ?
) 无效(并导致语法错误)。
如何防止 SQL 使用这种语句进行注入?
根据用户输入动态构建 SQL 语句并不是最好的主意。最好使用准备好的语句。但是,在这种情况下,似乎没有一种简单的方法可以使用 JPA EntityManager 执行补丁更新。
可以使用 JDBC 设置多个值。以下示例显示 Spring's JdbcTemplate:
的用法val items: List<Item> = ...
val statement =
"""
insert into item (field1, field2)
values (?,?)
on conflict on constraint arbeit_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
jdbcTemplate.batchUpdate(
statement,
object : BatchPreparedStatementSetter {
override fun setValues(statement: PreparedStatement, index: Int) {
val item = items[index]
statement.setString(1, item.field1)
statement.setInt(2, item.field2)
}
override fun getBatchSize(): Int = items.size
}
)