Hibernate:使用LIKE运算符时如何防范集合元素引发的SQL注入?
如何在LIKE查询中防范SQL注入?
嘿,这个问题我之前帮不少开发者踩过坑——你现在的代码直接把集合里的module值拼进SQL字符串里,这绝对是SQL注入的高危操作!万一有人往myCollection里塞个比如' OR 1=1 --的恶意值,整个WHERE条件直接被绕过,数据库里的数据就暴露了。
要解决这个问题,**预处理语句(PreparedStatement)**是业界公认的黄金方案,核心就是把SQL结构和动态参数彻底分开,让数据库把参数当作纯值处理,不会解析成SQL语句的一部分。下面是改写后的具体实现:
改写后的代码示例
StringBuilder sbQry = new StringBuilder("select * from tableName where 1=1"); List<String> queryParams = new ArrayList<>(); if (!myCollection.isEmpty()) { sbQry.append(" and ("); for (int i = 0; i < myCollection.size(); i++) { final String module = myCollection.get(i); // 添加精确匹配的占位符 sbQry.append("column = ?"); queryParams.add(module); // 处理LIKE匹配的模式:把-替换为%,然后用占位符传入 String likePattern = "J_" + module.replaceAll("-", "%"); sbQry.append(" or column like ?"); queryParams.add(likePattern); // 不是最后一个元素时添加OR分隔符 if (i != myCollection.size() - 1) { sbQry.append(" or "); } } sbQry.append(")"); } // 执行预处理查询 try (Connection conn = getYourDatabaseConnection(); // 替换成你的获取连接方法 PreparedStatement pstmt = conn.prepareStatement(sbQry.toString())) { // 逐个设置参数 for (int i = 0; i < queryParams.size(); i++) { pstmt.setString(i + 1, queryParams.get(i)); } // 执行查询并处理结果 try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { // 读取结果逻辑... } } } catch (SQLException e) { e.printStackTrace(); // 异常处理逻辑... }
为什么这样能防范注入?
- 参数与SQL分离:数据库会先预编译SQL模板(带
?占位符的部分),然后再把参数值填充进去,参数不会被当作SQL代码执行,彻底切断了注入的可能。 - 代码更易维护:动态逻辑和参数设置分开,后续修改查询条件时更清晰。
- 执行效率更高:预编译的SQL可以被数据库缓存,重复执行时性能更好。
额外注意点:处理LIKE通配符
如果你的module值可能包含LIKE的特殊字符(比如%、_),而你不希望这些字符被当作通配符解析,那可以加一个转义方法:
private static String escapeLikeSpecialChars(String input) { // 转义反斜杠、%、_这些LIKE特殊字符 return input.replace("\\", "\\\\") .replace("%", "\\%") .replace("_", "\\_"); }
然后在生成likePattern时先转义:
String escapedModule = escapeLikeSpecialChars(module); String likePattern = "J_" + escapedModule.replaceAll("-", "%");
这样用户输入的%或者_就只会被当作普通字符匹配,不会干扰LIKE的查询逻辑。
最后再提个醒:永远不要相信任何动态输入,哪怕是内部集合也可能被意外篡改。预处理语句是防范SQL注入最可靠的方式,尽量避免任何形式的字符串拼接来构建带动态值的SQL。
内容的提问来源于stack exchange,提问作者Vicky
相关产品推荐
相关产品推荐

