标签不执行sql拼接,仅将ognl表达式结果绑定为变量供#{ }使用;安全本质是避免${}拼接用户输入,改用配合#{ }实现参数化处理,全程走preparedstatement预编译防注入。

MyBatis 的 <bind></bind> 标签本身**不执行 SQL 拼接**,也不做字符串拼接操作,更不会“前置防注入”。它只是在运行时将一个 OGNL 表达式的结果绑定为一个新的变量,供后续 SQL 使用。所谓“安全的防注入前置拼接”,本质是**避免在 SQL 中直接用 ${} 拼接用户输入**,而应借助 <bind></bind> 配合 #{} 实现参数化处理,让模糊匹配逻辑由 Java 层或 MyBatis 安全接管。
为什么不能用 ${} 直接拼接 like 关键字
像 WHERE name LIKE '%${name}%' 这种写法极易引发 SQL 注入——攻击者传入 name=abc%' OR '1'='1 就能绕过条件。MyBatis 不会对 ${} 做任何转义或预编译,它直接插入 SQL 字符串中。
用 把模糊逻辑移到 Java 侧(推荐)
把通配符加在 Java 代码里,再作为完整参数传入,是最清晰、最可控的方式:
- Java 层调用前手动拼接:
String keyword = "%" + userInput.trim() + "%"; - Mapper 接口方法接收该已处理好的字符串:
selectByKeyword(String keyword) - XML 中直接
WHERE name LIKE #{keyword} - 这样全程走预编译,完全规避注入风险
用 在 XML 内部生成带通配符的绑定变量
如果坚持在 XML 中处理(比如多字段统一加 %),可用 <bind></bind> 调用 OGNL 的字符串操作:
<bind name="likeName" value="'%' + @org.apache.commons.lang3.StringUtils@defaultString(name, '') + '%'"></bind>
WHERE name LIKE #{likeName}
说明:
-
name是传入的原始参数(如String name) -
@...@defaultString(...)防止空指针,空值转为空字符串 -
#{likeName}仍走 PreparedStatement 占位符,安全 - 注意:OGNL 表达式里不能用 Java 的
+拼接 null,必须先判空或用defaultString
不推荐但需知道的误区
以下写法看似“防注入”,实则无效或危险:
-
<bind name="safeName" value="'%' + name + '%'"></bind> WHERE name LIKE '${safeName}'→ 仍是 ${},不安全 -
WHERE name LIKE CONCAT('%', #{name}, '%')→ 数据库函数可行,但跨库兼容性差(如 Oracle 不支持 CONCAT) - 用
<if test="name != null"></if>包裹 like 条件 → 只解决空值判断,不解决拼接安全问题
核心就一条:只要最终落到 SQL 中的用户输入内容是通过 #{} 注入的,MyBatis 就会交由 JDBC PreparedStatement 处理,天然防注入;<bind></bind> 只是帮你把“加 %”这件事从 Java 移到 XML,不改变底层安全机制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











