在我的 Java 类中,我有这样的方法。当我运行静态代码分析时,我在 sql.replaceAll 行中得到了 sql 注入。
studentFilter
值看起来像,schoolName = 'ABCD' AND state = 'TEXAS'
。如何解决这个问题?按照我的说法,我们不能在这里使用 PreparedStatement。
private Long getStudentCount(String studentFilter) {
private final NamedParameterJdbcTemplate template; //This is declared at class level
private static final String sql = "select count(name) from student
wheree marks > 90 AND
dateOfBirth = :dob AND
( --STUDENT_CONFIG--)";
MapSqlParameterSource sqlParams= new MapSqlParameterSource ();
sqlParams.addValue("dob", "19900101");
return template.queryForObject(sql.replaceAll("--STUDENT_CONFIG--", studentFilter, sqlParams, Long.class)
}
只需像为 DOB、IE 所做的那样参数化您的学生配置
sqlParams.addValue("studentConfig", studentFilter);
return template.queryForObject(sql, sqlParams, Long.class);
你不应该为
String
使用 studentFilter
类型,这将解决你的问题:
interface Condition {
String propertyName(); // Could be checked against explicit list of allowed names
String operation(); // Could be checked against explicit list of operations
String expectedValue(); // Could be injected through placeholder
}
List<Condition> studentFilter = ...
for (int i = 0; i < studentFilter.size(); i++) {
Condition c = studentFilter.get(i);
sql += " AND " + c.propertyName() + " " + c.operation() + " :placeHolder" + i;
sqlParams.addValue("placeHolder" + i, c.expectedValue());
}
我没有使用过NamedParameterJdbcTemplate,但逻辑应该没问题。
而不是用替换方法替换student config,尝试使用PreparedStatement/PreparedStatementCreator(在您的情况下)进行参数化查询,这可以防止SQL注入
有关主题的更多信息:https://www.baeldung.com/sql-injection
有关 NamedParameterJdbcTemplate 中 PreparedStatment 的更多信息:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.html