MySQL 防止 SQL 注入:参数化查询,新手必学的安全技巧
📅 2026/7/17 0:21:50
👁️ 阅读次数
📝 编程学习
前言
SQL 注入是 Web 最常见高危漏洞,新手拼接字符串写 SQL 极易中招,攻击者可篡改查询、拖库、删表。本文讲解注入原理、危险案例、标准参数化防御方案、日常开发规范。
一、SQL 注入漏洞原理(危险拼接写法)
后端直接拼接用户输入到 SQL 语句,攻击者输入特殊字符篡改 SQL 逻辑。
漏洞示例(伪代码,禁止使用)
// 危险:字符串拼接用户输入username String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = '" + pwd + "'";攻击者输入账号:admin' OR '1'='1拼接后 SQL 变为:
SELECT * FROM user WHERE username = 'admin' OR '1'='1' AND password = 'xxx';条件恒成立,无需密码直接登录任意账号;极端注入可执行DROP TABLE删库。
二、核心防御:参数化预编译查询(占位符?)
无论 Java MyBatis、Python pymysql、PHP 都支持预编译,将 SQL 结构与用户输入完全隔离,输入内容仅作为值,无法解析为 SQL 语法。
MySQL 标准预编译 SQL 模板
-- 使用?作为占位符,不拼接字符串 SELECT user_id,username FROM user WHERE username = ? AND password = ? AND is_deleted = 0;MyBatis 示例(安全写法 #{},底层参数化)
<select id="login" resultType="User"> SELECT user_id,username,status FROM user WHERE username = #{username} AND password = #{pwd} AND is_deleted = 0 </select>危险写法(${} 字符串拼接,极易注入)
<!-- 禁止!直接拼接输入,存在注入漏洞 --> SELECT * FROM user WHERE username = '${username}'三、额外多层防御手段
- 输入过滤校验账号、手机号、用户名做正则限制,仅允许数字、字母、少量符号,拦截
' " #--等注入特殊字符; - 最小权限账号程序数据库账号无 DROP、ALTER、CREATE 权限,即使注入也无法删表;
- 关闭数据库错误详情对外展示报错堆栈不返回前端,防止攻击者通过报错探测表名、字段;
- 禁止执行多语句连接参数关闭多 SQL 执行,拦截
;分隔多条恶意语句。
四、新手开发避坑清单
❌ 禁止直接拼接用户输入字符串到 SQL;
❌ 不使用${}接收用户输入(MyBatis);
❌ 不对前端传入的排序、分页字段直接拼接;
✅ 统一使用?占位符 /#{}参数化查询;
✅ 前端传参做长度、格式、字符校验;
✅ 数据库业务账号严格限制权限。
五、安全总结
防止 SQL 注入的唯一核心方案:参数化预编译查询,所有用户外部输入全部使用占位符传递,杜绝字符串拼接 SQL,从底层隔离恶意注入语句。
编程学习
技术分享
实战经验