【Java-MyBatis】MyBatis 如何防止 SQL 注入?

在这里插入图片描述

MyBatis防止SQL注入详解

1️⃣ SQL注入是什么?(故事举例)

想象一个银行系统:用户输入账号密码登录。如果开发人员直接拼接SQL:

String sql = "SELECT * FROM users WHERE account='"+account+"' AND pwd='"+pwd+"'";

黑客输入账号:admin' -- --是SQL注释符),密码随意。实际执行的SQL变成:

SELECT * FROM users WHERE account='admin' -- ' AND pwd='任意值'

相当于直接登录管理员账号!这就是SQL注入攻击。

2️⃣ MyBatis的防御机制

核心是通过 #{} 参数占位符 实现预编译:

<select id="findUser">
  SELECT * FROM users 
  WHERE account = #{account}  <!-- MyBatis自动处理为预编译参数 -->
  AND pwd = #{pwd}
</select>

执行过程:

  1. MyBatis先将SQL模板发送给数据库:
    SELECT * FROM users WHERE account=? AND pwd=?
  2. 数据库预编译该模板(确定语法结构)
  3. 再将参数值account='admin'--安全传递
  4. 最终执行时,参数始终被当作纯文本值,无法改变SQL结构
3️⃣ vs 危险写法 ${}
<!-- 危险!拼接SQL -->
<select id="findUser">
  SELECT * FROM users 
  WHERE account = '${account}'  <!-- 直接文本替换 -->
</select>

输入account=' OR 1=1 -- 时,SQL变成:

SELECT * FROM users WHERE account='' OR 1=1 -- '

所有账户泄露!

4️⃣ 特殊场景处理

必须用${}时(如动态表名/排序字段),需手动过滤

// 白名单校验
private static final Set<String> SAFE_COLUMNS = Set.of("name","age");

public String safeOrder(String column) {
  if(!SAFE_COLUMNS.contains(column)) 
    throw new IllegalArgumentException("非法字段");
  return "ORDER BY ${" + column + "}"; 
}
5️⃣ 额外防护建议
  • 📌 始终优先用 #{}
  • 📌 启用MyBatis的log4jdbc日志,监控实际SQL
  • 📌 对用户输入做正则校验(如账号只允许字母数字)
  • 📌 定期使用SQL注入扫描工具(如SQLMap)

总结

机制安全性原理使用场景
#{}✅ 安全预编译参数绑定99%场景推荐
${}❌ 危险字符串拼接动态表/列名需过滤
手动过滤⚠️ 可控白名单/类型校验不得已时使用

🔑 核心原则让数据和代码分离。预编译使SQL结构固定不变,用户输入仅作为"数据"传递,无法篡改"代码"结构。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java自学之旅

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值