侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

MyBatis动态SQL中如何防止SQL注入?请结合具体场景说明

2025-12-13 / 0 评论 / 4 阅读

题目

MyBatis动态SQL中如何防止SQL注入?请结合具体场景说明

信息

  • 类型:问答
  • 难度:⭐⭐

考点

动态SQL编写,SQL注入防范,MyBatis安全编码

快速回答

在MyBatis中防止SQL注入的核心要点:

  • 优先使用#{}占位符而非${}拼接SQL
  • 动态SQL中使用<if><choose>等标签时确保参数经过校验
  • 必须使用${}时需严格过滤输入(如白名单校验)
  • 对Like查询使用CONCAT函数或bind标签
  • 避免在XML中直接拼接未经验证的外部参数
## 解析

一、原理说明

SQL注入是攻击者通过构造特殊输入改变SQL语义的攻击方式。MyBatis中:

  • #{}原理:预处理语句(PreparedStatement),参数值会被安全替换,如WHERE id = ?
  • ${}原理:直接字符串拼接,如WHERE id = 1 OR 1=1,存在注入风险

二、代码示例

安全示例(使用#{})

<select id="findUser" resultType="User">
  SELECT * FROM users 
  WHERE username = #{name}  <!-- 安全 -->
</select>

危险示例(错误使用${})

<select id="findUser" resultType="User">
  SELECT * FROM users 
  WHERE username = '${name}'  <!-- 若name值为 ' OR '1'='1 将返回所有数据 -->
</select>

动态SQL安全写法

<select id="searchUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">
      AND username = #{name}  <!-- 安全 -->
    </if>
    <if test="minAge != null">
      AND age >= #{minAge}
    </if>
  </where>
</select>

Like查询防注入方案

<!-- 方案1:使用CONCAT -->
WHERE username LIKE CONCAT('%', #{keyword}, '%')

<!-- 方案2:使用bind标签 -->
<bind name="pattern" value="'%' + keyword + '%'" />
WHERE username LIKE #{pattern}

三、最佳实践

  • 强制规则:99%场景使用#{},仅动态表名/列名等元数据场景考虑${}
  • 输入校验:对${}参数做白名单校验(如只允许字母数字)
  • 框架特性:结合MyBatis-Plus等工具自动过滤危险字符
  • 防御纵深:Service层进行参数校验(如使用JSR 303)

四、常见错误

  • 错误1:在ORDER BY中使用${sortField}未校验
  • 错误2LIKE '%${value}%'直接拼接
  • 错误3:在<script>标签内混合使用#{}${}导致混乱

五、扩展知识

  • MyBatis参数处理流程#{}PreparedStatement.setXxx()
  • SQL注入检测工具:结合SQLMap进行DAO层安全测试
  • 企业级防护:使用Druid连接池配置WallFilter防御注入