目录
1、问题
2、原因
3、修改
1、问题
代码进行sonar扫描,扫描出存在sql注入问题。 问题代码如下:
//预编译
preparedStatement = conn.prepareStatement(sql);
//参数
initQueryParams(queryParams, preparedStatement);
//查询结果
resultSet = preparedStatement.executeQuery();
2、原因
因为用到了conn.prepareStatement,就感觉已经使用了预编译,应该没有sonar问题。因此找到了质量组申诉误报,然后他们给出结论如下:
(1)sql是接口传的,可能是delete、update影响比较大
(2)sql就算是查询sql,如果sql占位符是 ${}也没有真的实现预编译
如,select * from test where id = ${id},其实没有用到预编译
#、$区别
#预编译会替换成?, $直接进行的字符替换。
数据表或者order by后面的动态参数,必须用${},参数用#{}
如:select * from ${test} where id =#{id} order by ${order}
3、修改
(1)增加sql校验,校验sql是select语句
public static SwaggerResultUtil<String> checkSql(String sql, DbType dbType) { // 检测是否有语法错误 try { SQLUtils.parseStatements(sql, dbType); SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); SQLStatement statement = parser.parseStatement(); // 只允许查询语句 if (!(statement instanceof SQLSelectStatement)) { return SwaggerResultUtil.resultError(ExceptionCodeUtil.PARAM_ERROR_CODE_I4, "必须是select语句"); } } catch (Exception e) { log.error("sql有语法错误,错误信息:", e); return SwaggerResultUtil.resultError(ExceptionCodeUtil.PARAM_ERROR_CODE_I4, "sql语法错误:" + e.getMessage()); } return SwaggerResultUtil.resultSuccess(); }
(2)sql做替换${},换成?
根据业务,正常通过页面访问的sql,数据表是写死的,只有参数是动态的,所以用下面替换
sql = sql.replaceAll("\\$\\{\\w*\\}", "?");