MyBatis如何防止SQL注入?

MyBatis 主要通过 ​​预编译机制​​ 和 ​​安全的参数绑定​​ 防止 SQL 注入,同时需开发者遵循安全编码规范。以下是具体防护机制及最佳实践:


⚙️ 一、核心防注入机制

  1. ​预编译语句(#{}占位符)​

    • ​原理​​:MyBatis 默认使用 JDBC 的 PreparedStatement,将 SQL 语句与参数分离:
      • SQL 模板(如 SELECT * FROM users WHERE id = ?)先发送至数据库编译。举例:yczb.net.cn
      • 参数值通过 setXxx() 方法独立传递,数据库将其视为纯数据(非代码),自动转义特殊字符(如单引号 '\')。
    • ​代码示例​​:
      <select id="getUser" resultType="User">
          SELECT * FROM users WHERE id = #{id}  <!-- 安全 -->
      </select>yczb.net.cn
    • ​对比 ${} 的风险​​:${} 直接拼接字符串(如 ORDER BY ${column}),若参数来自用户输入,攻击者可注入 id; DROP TABLE users-- 等恶意代码。
  2. ​动态 SQL 标签的安全处理​
    MyBatis 的 <if><where><foreach> 等标签内部自动使用 #{} 机制,即使条件拼接也不会引入注入风险:

    <select id="searchUsers" resultType="User">
        SELECT * FROM users
        <where>
            <if test="name != null">  <!-- 安全 -->
                AND name = #{name}
            </if>
            <if test="role != null">
                AND role = #{role}www.yczb.net.cn
            </if>
        </where>
    </select>

    即使攻击者输入 name = 'admin' OR '1'='1',参数会被转义为普通字符串,无法改变 SQL 结构。示例:www.yczb.net.cn


⚠️ 二、${} 的高风险场景及安全使用

动态表名、列名等场景需使用 ${} 时,​​必须严格校验输入​​:

  • ​白名单校验​​:仅允许字母、数字、下划线等安全字符:
    public String safeTableName(String input) {
        if (!input.matches("^[a-zA-Z0-9_]+$")) {
            throw new IllegalArgumentException("非法表名");
        }m.yczb.net.cn
        return input;
    }
    <select id="queryByTable" resultType="map">
        SELECT * FROM ${tableName}  <!-- 确保 tableName 已校验 -->
    </select>
  • ​禁止在注解中使用 ${}​:
    @Select("SELECT * FROM ${table} WHERE id = #{id}")  // 危险!
    User getById(@Param("table") String table, @Param("id") Long id);
    表名若来自用户输入,可能导致注入。

🛡️ 三、其他安全增强措施

  1. ​输入参数过滤​
    • 业务层校验参数格式(如长度、字符集),拒绝非法输入(如使用正则 [a-zA-Z0-9]+ 过滤用户名)。
  2. ​最小权限原则​
    • 数据库账号仅授予必要权限(禁用 DROPEXECUTE 等危险操作)。示例:m.yczb.net.cn
  3. ​特殊查询的安全处理​
    • ​LIKE 查询​​:避免直接拼接 %
      SELECT * FROM users WHERE name LIKE CONCAT('%', #{keyword}, '%')
    • ​IN 查询​​:使用 <foreach> 自动转义:
      SELECT * FROM users WHERE id IN
      <foreach collection="ids" item="id" open="(" separator="," close=")">
          #{id}
      </foreach>m.yingchao.mo.cn

❌ 四、开发者常见错误与规避建议

​错误做法​​风险​​正确方案​
使用 ${} 拼接用户输入SQL 注入(如 ' OR 1=1 --优先用 #{},非用 ${} 则白名单校验
动态排序字段未校验(ORDER BY ${field}注入或语法错误校验字段名合法性
存储过程内部拼接未转义 SQL二次注入风险避免拼接,或强制参数化
注解中使用 ${}注入绕过改用 XML 配置 + 白名单

💎 总结:MyBatis 防注入最佳实践

  1. ​默认使用 #{}​:所有参数值传递均优先采用预编译占位符。
  2. ​动态 SQL 标签​​:安全处理条件拼接(<if><where>)。
  3. ${} 严格受限​​:仅用于表名/列名等非用户输入场景,且需白名单校验。
  4. ​输入过滤 + 权限控制​​:业务层校验 + 数据库最小权限。
  5. ​日志与测试​​:启用 SQL 日志审查,定期用 OWASP ZAP 等工具扫描漏洞。

ℹ️ 通过结合预编译机制、严格的 ${} 管控和业务层校验,可构建稳固的 SQL 注入防护体系。开发者的规范使用是防御的关键!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值