You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java代码SQL注入问题咨询:含字符串拼接漏洞的主方法分析

技术分析与修复方案:SQL注入漏洞(字符串拼接导致)

一、漏洞成因技术分析

咱们先拆解下你这段代码里的核心风险:
在else分支中,你直接把subName变量通过字符串拼接的方式嵌入到SQL条件里:

name = "= LOWER('" + subName + "')";

这种写法完全没有对变量做任何安全防护——哪怕现在subName是硬编码的"abhi",但如果后续这个变量变成用户可控的输入(比如前端传参、外部配置),攻击者就能构造恶意值篡改SQL逻辑。

举个例子,如果subName被修改为:

abhi'); DROP TABLE your_target_table; --

拼接后的SQL条件就会变成:

= LOWER('abhi'); DROP TABLE your_target_table; --')

数据库执行时会先完成原查询,紧接着执行DROP TABLE语句,直接造成数据丢失——这就是典型的SQL注入漏洞,攻击者可以通过构造恶意输入,执行任意未授权的数据库操作。

哪怕flag=true时的LIKE '%'现在看起来没问题,一旦flag的判断逻辑和用户输入挂钩,同样会引入注入风险。

二、修复方案:使用参数化查询(PreparedStatement)

解决SQL注入的行业标准方案就是用PreparedStatement替代Statement,它会把SQL逻辑和参数值完全分离:数据库先编译固定的SQL模板,再安全地注入参数值,从根源上避免恶意输入被解析成SQL指令。

修复后的完整代码示例:

public static void main(String[] args) { 
    boolean flag = false; 
    String subName = "abhi"; 
    try { 
        Class.forName("org.postgresql.Driver"); 
        // 建议用try-with-resources自动关闭资源,避免泄漏
        try (Connection c = DriverManager.getConnection("url","user", "password")) {
            
            String queryTemplate;
            if(flag){
                queryTemplate = "SELECT * FROM your_table WHERE your_column LIKE ?";
            } else {
                // 把LOWER()移到列上,或在应用层处理subName的小写(根据索引情况选择)
                queryTemplate = "SELECT * FROM your_table WHERE LOWER(your_column) = ?";
            }
            
            // 预编译SQL模板
            try (PreparedStatement ps = c.prepareStatement(queryTemplate)) {
                // 根据逻辑设置参数,JDBC自动处理转义
                if(flag){
                    ps.setString(1, "%");
                } else {
                    ps.setString(1, subName.toLowerCase());
                }
                
                // 执行查询
                try (ResultSet rs = ps.executeQuery()) {
                    // 后续处理ResultSet逻辑...
                }
            }
        }
    } catch (ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }
}

关键修复点说明:

  • 分离SQL与参数:用?作为占位符代替字符串拼接,数据库会将占位符位置的内容当作纯数据处理,不会解析为SQL指令
  • 预编译机制PreparedStatement会预先编译SQL模板,不仅更安全,还能提升重复执行相同结构SQL的性能
  • 参数安全注入:通过setString等方法设置参数,JDBC会自动处理特殊字符的转义,彻底避免恶意输入破坏SQL结构
  • 资源自动管理:用try-with-resources语法自动关闭连接、Statement、ResultSet,避免手动关闭遗漏导致的资源泄漏

额外建议

  • 永远不要信任任何用户可控的输入,哪怕是内部生成的变量,也要假设它可能被篡改
  • 优先使用ORM框架(如MyBatis、Hibernate),它们底层基于参数化查询,能进一步降低手动编写SQL的出错概率
  • 如果必须手动写SQL,严格禁止任何形式的字符串拼接,所有变量都通过PreparedStatement的参数方法传入

内容的提问来源于stack exchange,提问作者ashim panda

火山引擎 最新活动