
1) 【一句话结论】防止SQL注入的核心是使用参数化查询(预编译语句),通过将SQL语句与用户输入参数分离,避免恶意输入被解释为SQL代码,从而阻断注入攻击。
2) 【原理/概念讲解】SQL注入是指攻击者通过在输入字段插入恶意SQL代码,绕过验证逻辑执行非预期数据库操作。例如,用户输入' OR 1=1 --会改变查询逻辑(如原本SELECT * FROM users WHERE username = 'admin'变成SELECT * FROM users WHERE username = '' OR 1=1 --,导致所有用户被查询)。参数化查询(如Java的PreparedStatement、Python的psycopg2等)将SQL语句的参数用占位符(如?)表示,由数据库引擎处理参数,用户输入仅作为参数传递,不会参与SQL解析,从而防止注入。类比:填空题中,用户填答案(参数),而非修改题目(SQL语句),题目(SQL结构)与答案(参数)分离,避免答案影响题目逻辑。
3) 【对比与适用场景】
| 方式 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 字符串拼接 | 将SQL语句与用户输入直接拼接成字符串 | SQL语句与参数混合,用户输入可能被解释为SQL代码 | 简单查询,开发时未考虑安全 | 容易被注入,需手动转义,复杂查询易出错 |
| 参数化查询 | 将SQL语句的参数用占位符表示,参数单独传递 | SQL语句与参数分离,参数由数据库处理 | 所有需要用户输入的查询(尤其是动态查询) | 需预编译,可能存在参数类型匹配问题 |
4) 【示例】(以Java为例):
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
// 若username为"admin' OR '1'='1",实际执行:SELECT * FROM users WHERE username = 'admin' OR '1'='1'(导致注入)
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username); // 参数1对应第一个?,用户输入作为参数传递
ResultSet rs = pstmt.executeQuery();
5) 【面试口播版答案】
“面试官您好,关于防止SQL注入,核心是使用参数化查询(预编译语句)。SQL注入的原理是攻击者通过输入恶意SQL代码绕过验证,比如输入' OR 1=1 --会改变查询逻辑。参数化查询通过将SQL语句和参数分离,用占位符(如?),由数据库处理参数,用户输入仅作为参数传递,不会参与SQL解析,从而阻断注入。比如错误实现用字符串拼接,会把用户输入直接拼入SQL,导致注入;正确实现用PreparedStatement,把用户输入作为参数,数据库只处理参数,不会执行恶意SQL。比如Java中,错误写法是SELECT * FROM users WHERE username = '" + username + "',这样输入admin' OR '1'='1就会导致注入;正确写法是SELECT * FROM users WHERE username = ?,用pstmt.setString(1, username),无论输入什么,数据库都只按参数处理,不会执行恶意SQL。总结来说,参数化查询是防止SQL注入最有效的方法,因为它从根本上隔离了用户输入和SQL语句的执行逻辑。”
6) 【追问清单】
'),无需手动转义,而字符串拼接需手动转义,易遗漏。7) 【常见坑/雷区】
'')能完全防止注入。pstmt.setString(1, input)中占位符数量不匹配)。