我正在使用 sql 查询
,例如
String query = "Select max(case when UPPER(key)='firstname' then value end) as firstNameName, , ... order by "+orderBy;
result = em.createNativeQuery(query).getResultList();
em.close();
出于某种原因,我将不得不使用动态 +orderBy
。其中 orderBy =firstname ASC,lastname DESC
等。尝试使用 .setParameter(1, orderedBy)
但在这种情况下,我没有得到预期的排序结果。
最佳答案
为了避免 sql 注入(inject)威胁,您首先需要删除附加参数到您的查询。当您在应用程序中附加参数时,攻击者可以劫持您的 sql 代码(例如使用撇号和其他方式)
例如:
如果您的查询是 "select * from table where name="+id
攻击者可以传递给字段值,例如:
'John' or 1=1;
->查看你在这个表中的所有记录
甚至
'John' or 1=1;Delete all from users;'
-> 从用户表中删除所有条目。
劫持查询可以通过输入清理、输入白名单/黑名单(从输入中删除不需要的字符/定义允许或不允许的字符列表)等机制来避免。大多数现代框架框架(例如 JDBC/JPA/Hibernate)都可以提供针对这种威胁的保护。
综上所述,我们应该考虑以下情况:
考虑sql where参数:
例如 JDBC 提供准备好的语句,您可以在其中定义一个变量在您的 sql 中,然后由框架替换它
在你的情况下,JPA 实现(Hibernate)也有避免这种威胁的机制,也通过参数化查询和位置参数:
- 通过 native 查询位置参数:
Query q = em.createNativeQuery("SELECT count(*) FROM mytable where username = ?1");
q.setParameter(1, "test");
- 通过命名参数(jplq)
Query q = em.createQuery("SELECT count(*) FROM mytable where username = :username");
q.setParameter("username", "test");
考虑 orderBy 参数:
CriteriaQuery
/spring规范
CriteriaBuilder cb = this.entityManager
.getCriteriaBuilder();
CriteriaQuery<RESULT> criteria = cb.createQuery(RESULT.class);
Root<RESULT> root = criteria.from(RESULT.class);
return this.entityManager.createQuery(
criteria.select(root).orderBy(cb.asc(root.get("ORDER_BY_FIELD"))))
.getResultList();
更多关于 criteriaQueries 的使用和配置 here
- 通过预先构建的 spring 特定
Sort
参数传递orderBy
(使用 spring-data 库)
Sort sort = Sort.by(Sort.Direction.ASC, "criteria");
em.createQuery(QueryUtils.applySorting(yourSqlQuery_withoutSorting,sort));
- 使用带有 spring-data 库的 @Query 注释方法:
您可以使用更少的样板代码(无需注入(inject) entityManager 和创建 nativeQuery)实现相同的结果,只需使用 @Query
注释来注释方法:
@Query("select u from User u where u.lastname like ?1%")
List<User> findByAndSort(String lastname, Sort sort);
注意:
本地与非本地(jpql):
JOQL 查询独立于数据库供应商(MySQL、PostGres、Oracle、DB2),当您需要使用不同供应商不同的数据库特定功能时,nativeQueries 的使用更加集中。
举个简单的例子jpql不能支持原生[With]
2子句 PLSQL 标准函数
关于您的修改:
您可以尝试应用以下 sql 技巧进行动态排序:
SELECT param1, param2 ...
FROM ...
ORDER BY case when :sortParam='name asc' then name asc END
case when :sortParam='name desc' then name desc END
....
else 0
关于java - 在 Spring JPA 中避免 SQL 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63997976/