当前位置: 首页 > news >正文

MyBatis 中 ${} 与 #{} 的区别与 SQL 注入防范教程

一、核心概念

在 MyBatis 的 XML 映射文件中,有两种方式将参数拼接到 SQL 语句中:

  • ${}:直接字符串拼接(文本替换),不处理特殊字符,存在 SQL 注入风险
  • #{}:预编译占位符(?),自动过滤特殊字符,能防止 SQL 注入

二、代码示例分析

以下是一个模糊查询的 MyBatis XML 配置和测试用例:

1. XML 映射文件
<select id="findByNameLike2" resultType="Emp">select * from emp where name like '${name}'
</select>
2. 测试用例
@Test
public void testFindByNameLike2() throws IOException {// 正常查询:传入 "%张%"mapper.findByNameLike2("%张%").forEach(System.out::println);// 生成SQL:select * from emp where name like '%张%'// 恶意输入:传入 "abc' or '1=1----"mapper.findByNameLike2("abc' or '1=1----").forEach(System.out::println);// 生成SQL:select * from emp where name like 'abc' or '1=1----'
}

三、${} 的 SQL 注入风险详解
1. 正常输入场景
  • 参数"%张%"
  • 生成 SQLselect * from emp where name like '%张%'
  • 效果:正确查询名字包含“张”的员工。
2. 恶意输入场景
  • 参数"abc' or '1=1----"
  • 生成 SQL
select * from emp where name like 'abc' or '1=1----'
  • 解析
    由于 '1=1' 是恒真条件,此 SQL 会返回所有员工数据,导致数据泄露。

四、#{} 的预编译机制
1. 使用 #{} 的修改版
<select id="findByNameLikeSafe" resultType="Emp">select * from emp where name like #{name}
</select>
2. 测试用例对比
@Test
public void testFindByNameLikeSafe() {// 正确用法:传入 "%张%"mapper.findByNameLikeSafe("%张%");// 生成SQL:select * from emp where name like ?// 恶意输入:传入 "abc' or '1=1----"mapper.findByNameLikeSafe("abc' or '1=1----");// 生成SQL:select * from emp where name like ?// 参数值:被转义为 "abc' or '1=1----"(视为普通字符串)
}
  • 效果:恶意参数会被视为整体字符串,无法改变 SQL 结构。

五、使用建议与最佳实践
1. 优先使用 #{}
  • 所有用户输入或外部参数必须使用 #{},尤其是 WHERE 条件中的值。
2. 谨慎使用 ${}
  • 适用场景:动态表名、动态列名等非用户输入场景。
  • 风险控制:若必须使用 ${},需手动过滤危险字符(如单引号 ')。
3. 模糊查询的正确写法
  • 安全方式:在参数中拼接 %,而非 SQL 中。
// Java 代码中处理
String name = "%" + userInput + "%";
mapper.findByNameLikeSafe(name);

六、总结
特性${}#{}
处理方式直接替换预编译占位符
SQL 注入风险高风险无风险
适用场景动态表名/列名用户输入、条件值
性能无额外解析预编译优化

始终遵循规则:用户输入必须通过 #{} 传递!

相关文章:

  • 安装Python和配置开发环境
  • PHP 连接和使用 Kafka 的指南
  • Spring AI 与 Hugging Face 深度集成:打造高效文本生成应用
  • 我们来学mysql -- 安装8.4版本
  • 通信网络编程——JAVA
  • AWS EC2源代码安装valkey命令行客户端
  • PHP 代理服务器:如何在 PHP 中设置代理
  • STC15W408AS计数器
  • 分水岭算法:从逻辑学角度看图像分割的智慧
  • 图像匹配导航定位技术 第 12 章
  • 报表制作工具PK:山海鲸报表和Looker,谁更适合新手使用?
  • 如何使用 WMIC 命令在 Windows 11 或 10 上卸载软件
  • 机器学习实战:归一化与标准化的选择指南
  • MAC-OS X 命令行设置IP、掩码、网关、DNS服务器地址
  • # 实时英文 OCR 文字识别:从摄像头到 PyQt5 界面的实现
  • Go 语言 slice(切片) 的使用
  • Git安装教程及常用命令
  • 数据结构-树(2)
  • [python] 面向对象的三大特性-封装及新式类
  • Python制作Dashboard【待续】
  • 美国拟向阿联酋和沙特AI公司出口数十万枚芯片
  • 演员黄晓明、金世佳进入上海戏剧学院2025年博士研究生复试名单
  • 尹锡悦涉嫌发动内乱案举行第三次庭审
  • 何立峰:中方坚定支持多边主义和自由贸易,支持世贸组织在全球经济治理中发挥更大作用
  • 第一集丨《亲爱的仇敌》和《姜颂》,都有耐人寻味的“她”
  • 母亲节|写给妈妈