${} 不防 SQL 注入,仅限表名、列名、排序方向等无法参数化的语法结构使用,且必须经白名单校验;禁止用于 WHERE 值、LIKE 内容、IN 列表等场景。

`${}` 本身不防 SQL 注入,它就是字符串拼接,风险天然存在。防止风险的关键不是“怎么用 `${}` 更安全”,而是**严格限制它的使用场景,并在必须用时加多重防护**。
只在无法参数化的 SQL 结构中才允许用 `${}`
数据库表名、列名、排序方向(ASC/DESC)、分表后缀等,属于 SQL 语法组成部分,不能加引号,也不能走预编译,此时 `#{}` 失效,才考虑 `${}`。但前提是:这些值绝不能直接来自用户输入。
- 表名必须来自配置项或枚举类,比如
OrderStatusTable.TB_ORDER_2026 - 排序字段只能是预设白名单中的几个,如
"id", "create_time", "amount" - 排序方向只接受
"ASC"或"DESC",其他一律拒绝
Java 层必须做白名单校验,校验通过后再传给 `${}`
不能把前端传来的任意字符串直接塞进 `${sortField}`。要在 Service 或 Controller 中拦截并校验:
- 定义合法字段集合:
private static final SetALLOWED_SORT_FIELDS = Set.of("id", "name", "status"); - 收到参数立即判断:
if (!ALLOWED_SORT_FIELDS.contains(sortField)) { throw new IllegalArgumentException("非法排序字段"); } - 校验通过后,再作为参数传入 Mapper,XML 中写
ORDER BY ${sortField} ${sortOrder}
避免在动态 SQL 标签里混用 `${}`
`
- 错误写法:
ORDER BY ${sort} - 正确做法:先校验,再决定是否进入该 `
` 块;或者改用 ` ` 预处理为可信变量,再引用
绝对禁止的 `${}` 用法
以下情况无论什么理由都不能用 `${}`,必须重构:
- WHERE 条件值,如
WHERE username = ${username}→ 改用#{username} - LIKE 模糊匹配内容,如
WHERE name LIKE '%${keyword}%'→ 改为 Java 拼通配符或数据库函数,仍走#{keyword} - IN 查询列表,如
WHERE id IN (${ids})→ 改用 `` + #{id} - 整段条件拼接,如
WHERE ${condition}→ 属于高危反模式,应拆解为多个 `` + `#{}`
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











