MySQL 防止 SQL 注入:参数化查询,新手必学的安全技巧

📅 2026/7/17 0:21:50 👁️ 阅读次数 📝 编程学习
MySQL 防止 SQL 注入:参数化查询,新手必学的安全技巧

前言

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}'

三、额外多层防御手段

  1. 输入过滤校验账号、手机号、用户名做正则限制,仅允许数字、字母、少量符号,拦截' " #--等注入特殊字符;
  2. 最小权限账号程序数据库账号无 DROP、ALTER、CREATE 权限,即使注入也无法删表;
  3. 关闭数据库错误详情对外展示报错堆栈不返回前端,防止攻击者通过报错探测表名、字段;
  4. 禁止执行多语句连接参数关闭多 SQL 执行,拦截;分隔多条恶意语句。

四、新手开发避坑清单

❌ 禁止直接拼接用户输入字符串到 SQL;

❌ 不使用${}接收用户输入(MyBatis);

❌ 不对前端传入的排序、分页字段直接拼接;

✅ 统一使用?占位符 /#{}参数化查询;

✅ 前端传参做长度、格式、字符校验;

✅ 数据库业务账号严格限制权限。


五、安全总结

防止 SQL 注入的唯一核心方案:参数化预编译查询,所有用户外部输入全部使用占位符传递,杜绝字符串拼接 SQL,从底层隔离恶意注入语句。