You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:25:16