【Java后端】MyBatis 与 MyBatis-Plus 如何防止 SQL 注入?从原理到实战
在日常开发中,SQL 注入是一种常见但危害巨大的安全漏洞。如果你正在使用 MyBatis 或 MyBatis-Plus 进行数据库操作,这篇文章将带你系统了解:这两个框架是如何防止 SQL 注入的,我们又该如何写出安全的代码。
什么是 SQL 注入?
SQL 注入(SQL Injection)是指攻击者通过输入恶意 SQL 语句,干扰原本正常的数据库查询,从而达到绕过登录、获取数据、甚至删除数据库的目的。
举个例子:
SELECT * FROM user WHERE name = 'admin' AND password = '123456' OR '1'='1'
如果我们将用户输入直接拼接到 SQL 中,攻击者就可能利用 OR '1'='1'
这样的语句,绕过身份验证。
MyBatis 如何防止 SQL 注入?
使用 #{}
占位符(参数绑定)
MyBatis 的推荐做法是:使用 #{}
进行参数绑定。这是最有效的 SQL 注入防范方式。
<select id="selectUserByName" resultType="User">SELECT * FROM user WHERE name = #{name}
</select>
#{name}
会被转换为 JDBC 的PreparedStatement
参数,占位符?
。- 由 MyBatis 自动将变量安全注入,避免注入风险。
避免 ${}
动态拼接
<select id="selectUserByName" resultType="User">SELECT * FROM user WHERE name = '${name}'
</select>
${}
会直接将用户输入拼接到 SQL 字符串中。- 攻击者可以输入
' OR 1=1 --
这样的语句,造成严重后果。
总结:
- 使用
#{}
:安全 - 避免使用
${}
:易受攻击
MyBatis-Plus 如何防止 SQL 注入?
MyBatis-Plus 是 MyBatis 的增强工具,大量简化了开发。它默认使用参数绑定机制,在大多数情况下天然具备防注入能力。
条件构造器安全性
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", userName);
userMapper.selectList(wrapper);
.eq("name", userName)
会使用PreparedStatement
自动绑定参数。- 比手写 SQL 更简洁也更安全。
apply 使用注意事项
有时候你可能需要执行一些复杂的 SQL 片段,比如使用 SQL 函数:
wrapper.apply("DATE_FORMAT(create_time,'%Y-%m-%d') = {0}", dateStr);
- 使用
{0}
绑定参数,是安全的。 - 直接拼接字符串不安全:
wrapper.apply("DATE_FORMAT(create_time,'%Y-%m-%d') = '" + dateStr + "'");
实战建议
- 优先使用 MyBatis-Plus 提供的 API,如 Wrapper、LambdaQueryWrapper
- MyBatis XML 中,禁止使用
${}
,一律使用#{}
- 自定义 SQL 时,确保参数使用绑定方式
- 开启 SQL 日志,排查拼接风险
- 可选:配合 SQL 审计工具做自动扫描
如果你觉得这篇文章对你有帮助,不妨点个赞