在 Java + MyBatis 中,防 SQL 注入的核心原则是:永远不要把用户输入直接拼接到 SQL 中,而是使用 参数化查询(预编译)。
下面按常见场景说明。
#{}(最推荐)MyBatis 中 #{} 会被转换为 PreparedStatement 参数,自动转义。
Mapper XML
<select id="getUser" resultType="User">
SELECT * FROM user
WHERE username = #{username}
</select>
Java
userMapper.getUser("admin");
✅ 生成的 SQL:
SELECT * FROM user WHERE username = ?
✅ 用户输入 ' OR '1'='1 也不会生效
@Param + Mapper 接口User selectByUsername(@Param("username") String username);
WHERE username = #{username}
@Select("SELECT * FROM user WHERE username = #{username}")
User getUser(String username);
${} 拼接 SQL(高危)<select id="getUser" resultType="User">
SELECT * FROM user
WHERE username = '${username}'
</select>
❌ 直接拼接字符串
❌ 用户输入:' OR '1'='1
❌ SQL 变成:
SELECT * FROM user WHERE username = '' OR '1'='1'
⚠️ 除非万不得已,禁止使用 ${}
String sql = "SELECT * FROM user WHERE username = '" + username + "'";
❌ 极度危险
${} 什么时候能用?只能用于“非用户输入”的场景
✅ 示例(安全):
ORDER BY ${column}
前提:
column 来自 白名单if (!"id".equals(column) && !"name".equals(column)) {
column = "id";
}
<if test="username != null">
AND username = #{username}
</if>
<if test="username != null">
AND username = '${username}'
</if>
userMapper.selectOne(
Wrappers.<User>lambdaQuery()
.eq(User::getUsername, username)
);
MyBatis 防注入:用
#{},别用${},不拼 SQL,校验输入。
如果你有 具体 Mapper 代码或场景(排序 / 动态表名 / in 查询),我可以帮你改安全技术点。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。