在写动态 SQL 时,“安全”主要指的是:防止 SQL 注入、避免语法错误、便于维护和排查问题。下面从原则、写法和常见框架示例来说。
❌ 错误示例(极其危险):
"SELECT * FROM user WHERE name = '" + username + "'"
✅ 正确做法:使用参数化查询(占位符)
无论是否动态,都只拼 结构,不拼 值。
SELECT * FROM user
WHERE 1=1
AND name = ?
AND age > ?
可以动态拼接:
不能动态拼接值
比如排序字段:
❌ 危险:
ORDER BY ${column}
✅ 安全:
List<String> allowed = Arrays.asList("id", "name", "create_time");
if (!allowed.contains(column)) {
column = "id";
}
<if> + #{}<select id="listUser">
SELECT * FROM user
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
✅ #{} → 预编译参数(安全)
❌ ${} → 字符串替换(危险,仅用于白名单)
<if test="sortField == 'name' or sortField == 'id'">
ORDER BY ${sortField}
</if>
或 Java 中控制:
if (!ALLOWED.contains(sortField)) sortField = "id";
CriteriaBuilder cb = ...
Predicate p = cb.equal(root.get("name"), name);
jdbcTemplate.query(
"SELECT * FROM user WHERE name = ?",
name
);
动态 SQL 安全 = 结构可动态 + 值必须参数化 + 非值部分白名单
如果你用的是 MyBatis / JPA / 原生 JDBC / Python / Go,我可以给你对应语言的具体模板。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。