SQL注入是什么?生产环境怎么防御?
先说结论
SQL注入的核心是:用户输入被当作SQL代码执行了。防御的核心是:参数化查询(Prepared Statement),让用户输入永远只是“数据”,不会被解释为“代码”。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
SQL注入是最古老但仍然最常见的Web安全漏洞之一。作为数据开发,虽然不直接写业务代码,但理解SQL注入的原理和防御方法是基本素养。而且我们编写的存储过程、报表SQL也可能有注入风险。
一个简单的注入示例
-- 登录接口的SQL(字符串拼接,有注入风险)
SELECT * FROM users
WHERE username = '' OR 1=1 --'
AND password = 'anything';
-- 用户输入的username是: ' OR 1=1 --
-- 实际执行的SQL变成:
-- SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = 'anything'
-- OR 1=1 永远为真,-- 注释掉后面的条件
-- 结果:返回所有用户!
防御方案一:参数化查询(核心防御)
// ✖ 危险:字符串拼接
String sql = "SELECT * FROM users WHERE username = '" + input + "'";
// ✔ 安全:参数化查询
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, input); // input被当作数据,不会被解释为SQL
参数化查询是防SQL注入的唯一正确方法。输入过滤、转义等方法都不可靠,因为总有绕过的方法。
防御方案二:最小权限原则
应用程序连接MySQL的账号不应该有DROP、ALTER等危险权限。即使被注入了,也不能删库删表。
-- 为应用程序创建专用账号,只给必要权限
CREATE USER 'app_user'@'%' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'%';
-- 没有DROP、ALTER、CREATE权限
数据开发也要注意
作为数据开发,我们写的存储过程、报表SQL、数据同步脚本里如果有动态拼接SQL的情况,也有注入风险。比如根据用户输入的表名动态查询,如果不做校验,用户可能输入“users; DROP TABLE orders”。
总结
SQL注入的核心防御是参数化查询。配合最小权限原则、输入校验、WAF等多层防御。面试时能举个注入的例子、说清楚参数化查询的原理,再加上最小权限的实践,就很完整。
最后一篇是最重要的综合题:请描述你在项目中是怎么使用MySQL的。
你们项目里遇到过SQL注入吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长