SQL 注入是攻击者把恶意 SQL 片段拼进查询参数,改变原有语句语义。例如登录查询 SELECT * FROM user WHERE name='${name}',传入 ' OR '1'='1 就绕过认证。根因是代码与数据混在同一通道,解释器无法区分。
预编译(Prepared Statement)能根治:SQL 模板先发给数据库解析、编译好执行计划,参数再以纯数据方式绑定传输,参数永远不会被当作 SQL 语法解析,无论内容是什么都只是字符串值。
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM user WHERE name = ?");
ps.setString(1, name); // 参数仅作为数据
注意两点误区:一是预编译无法保护标识符(表名、列名、ORDER BY 字段),这些必须白名单校验;二是某些驱动的"伪预编译"(本地拼接)不防注入。纵深防御还包括:ORM 参数化、最小权限数据库账号、WAF、错误信息不外泄。追问方向:二次注入、宽字节注入、盲注类型(布尔/时间)。