{}安全因其采用PreparedStatement预编译,参数作为纯数据绑定;${}危险因直接字符串替换,用户输入可篡改SQL结构,仅限表名、列名等动态语法场景且须白名单校验。

MyBatis 本身不自动防注入,它只提供工具;是否安全,完全取决于你怎么用 #{} 和 ${}。
为什么 #{} 是安全的,而 ${} 是危险的?
关键区别在于执行时机和数据库处理方式:#{} 触发 JDBC 的 PreparedStatement 预编译流程,参数值在 SQL 解析之后才被绑定,永远作为纯数据;${} 是 MyBatis 在生成 SQL 字符串阶段就做文本替换,相当于手动拼接——用户输入直接进 SQL 模板,数据库还没见到它,结构就已经被改写了。
常见错误现象:
- 用
${username}做 WHERE 条件 → 输入admin' OR '1'='1直接拖库 - 用
${sortField}做 ORDER BY → 输入id; DROP TABLE user; --可能触发多语句执行(取决于数据库配置)
使用场景限制:
立即学习“Java免费学习笔记(深入)”;
-
#{}可用于所有值类参数:WHERE、INSERT VALUES、UPDATE SET 等 -
${}仅限无法参数化的部分:表名、列名、ORDER BY 字段、GROUP BY 表达式等
like 模糊查询怎么写才不踩坑?
这是高频重灾区。很多人图省事写成 LIKE '%${keyword}%',等于主动开门。
正确做法是把通配符加在 Java 层,再传给 #{}:
- DAO 层接收原始 keyword,如
"张" - Service 层处理为
"%张%",再调用 mapper 方法 - XML 中写成
WHERE username LIKE #{keyword}
如果必须在 XML 里加通配符(比如复用 mapper),可用 MyBatis 内置函数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
<select id="findByNameLike">
SELECT * FROM user WHERE username LIKE CONCAT('%', #{keyword}, '%')
</select>注意:MySQL 的 CONCAT 安全,但 Oracle 要用 ||,PostgreSQL 用 || 或 concat() —— 函数本身不引入注入,前提是参数仍走 #{}。
动态排序、分表、字段列表怎么安全地用 ${}?
只要用了 ${},就必须白名单校验,不能靠正则过滤或黑名单拦截。
示例(Java 层校验):
- 定义允许的排序字段:
private static final Set<String> ALLOWED_SORT_FIELDS = Set.of("create_time", "username", "status"); - 校验逻辑:
if (!ALLOWED_SORT_FIELDS.contains(sortField)) throw new IllegalArgumentException("非法排序字段"); - XML 中放心用:
ORDER BY ${sortField} ${sortOrder},但sortOrder也得单独白名单(只允许"ASC"/"DESC")
性能影响:白名单判断是 O(1) 查找,几乎无开销;但若用正则匹配字段名(如 ^[a-zA-Z_][a-zA-Z0-9_]*$),可能被绕过(如 user_name-- 后接注释),且不如白名单语义清晰。
MyBatis-Plus 的 Wrapper 是否绝对安全?
绝大多数链式调用(如 .eq("name", input)、.like("desc", input))底层仍走 PreparedStatement,是安全的。
但要注意两个例外:
-
apply()方法:如果写成wrapper.apply("score >= " + userInput),就是硬编码拼接,立刻失守 -
last()方法:直接追加原生 SQL 片段,例如wrapper.last("LIMIT " + limit),limit 若来自用户且未校验,可能被注入
安全写法:
-
apply("score >= {0}", userInput)→ 占位符模式,安全 -
last("LIMIT ?", limit)→ 支持参数绑定,安全
容易被忽略的点:Wrapper 的 in()、between() 等方法接受集合或范围值,它们内部做了预处理,但如果你传入的是运行时拼出来的字符串(比如手动 String.join(",", ids) 再塞进 inSql()),就又退回到风险区。

















