动态 SQL 本身并不“天然安全”,是否安全取决于你“怎么写”。
如果处理不当,它非常容易导致 SQL 注入,这是最常见、危害最大的安全问题之一。
下面从原理、风险、安全写法几个角度说明。
动态 SQL 指的是 SQL 语句在运行时拼接生成,而不是直接写死,例如:
SELECT * FROM user WHERE name = ' + userName + '
或:
"SELECT * FROM user WHERE id = " + id
String sql = "SELECT * FROM user WHERE name = '" + name + "'";
如果用户输入:
name = ' OR '1'='1
最终 SQL 变成:
SELECT * FROM user WHERE name = '' OR '1'='1'
✅ 直接查全表,甚至被删库
✅ 只要参数不拼 SQL,而是作为参数传入
PreparedStatement ps =
conn.prepareStatement("SELECT * FROM user WHERE name = ?");
ps.setString(1, name);
✅ 安全
✅ 安全:
<select id="findUser">
SELECT * FROM user
<where>
<if test="name != null">
AND name = #{name}
</if>
</where>
</select>
❌ 不安全(字符串拼接):
AND name = '${name}'
结论:MyBatis 中
#{}安全,${}危险
✅ 合理且安全的使用场景:
⚠️ 表名 / 排序字段 不能参数化,只能:
if ("create_time".equals(sortField)) {
sql += " ORDER BY create_time";
}
动态 SQL 本身不是问题,拼 SQL 才是问题。
参数化 = 安全,拼接 = 高危。
如果你愿意,可以把你现在的 SQL 或代码贴出来,我可以帮你判断 是否安全、如何改。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。