Mybatis如何防止sql注入

MyBatis 通过多种机制防止 SQL 注入攻击,核心在于 预编译语句安全的参数绑定,但需开发者遵循最佳实践才能完全规避风险。以下是详细解析和具体防护方案:

一、核心防注入机制

  1. 预编译语句(PreparedStatement)

    • 原理:MyBatis 底层使用 JDBC 的PreparedStatement,将 SQL 语句与参数分离。

      • SQL 模板先发送到数据库编译(如 SELECT * FROM users WHERE id = ?)。

      • 参数值通过setXxx()方法独立传递,数据库将其视为纯数据而非可执行代码,自动转义特殊字符(如单引号' → \')。

    • 代码示例:

      <select id="getUser" resultType="User">
          SELECT * FROM users WHERE id = #{id}  <!-- 安全 -->
      </select>
  2. 参数化占位符 #{}

    • 作用#{} 会被替换为 PreparedStatement 的占位符 ?,确保参数值安全转义。

    • 对比 ${} 的风险:

      • ${}直接拼接字符串到 SQL 中(如 ORDER BY ${column} ),若参数来自用户输入,可能注入恶意代码。

      • 危险示例:

        <!-- 攻击者输入 column = "id; DROP TABLE users--" -->
        SELECT * FROM users ORDER BY ${column}  <!-- 导致删除表 -->

二、动态 SQL 的安全处理

MyBatis 的动态 SQL 标签(<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}
        </if>
    </where>
</select>

三、${} 的高风险场景及安全使用

当必须使用 ${} 动态替换表名、列名时,需严格校验输入:

  1. 白名单校验

    public String safeTableName(String input) {
        // 仅允许字母、数字、下划线
        if (!input.matches("^[a-zA-Z0-9_]+$")) {
            throw new IllegalArgumentException("非法表名");
        }
        return input;
    }
    <select id="queryByTable" resultType="map">
        SELECT * FROM ${tableName}  <!-- 确保 tableName 已校验 -->
    </select>
  2. 避免在注解中使用 ${}

    // 危险!攻击者可控制表名
    @Select("SELECT * FROM ${table} WHERE id = #{id}")
    User getById(@Param("table") String table, @Param("id") Long id);

四、其他安全增强措施

  1. 输入参数过滤

    • 在业务层校验参数格式(如长度、字符集),拒绝非法输入。

  2. 最小权限原则

    • 数据库账号仅授予必要权限(如禁用DROP、EXECUTE等危险操作)。

  3. Like 查询安全写法

    <!-- 正确方式:避免直接拼接 % -->
    SELECT * FROM users WHERE name LIKE CONCAT('%', #{keyword}, '%')
  4. IN 查询安全处理

    <!-- 使用 foreach 标签自动转义 -->
    SELECT * FROM users WHERE id IN
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>

五、测试与维护

  1. SQL 日志审查

    • 启用 MyBatis SQL 日志,检查生成的语句是否含未转义参数。

  2. 安全工具扫描

    • 使用 OWASP ZAP、SQLMap 等工具主动检测注入漏洞。

  3. 依赖更新

    • 保持 MyBatis 及数据库驱动的最新版本,修复已知漏洞。

防注入手段总结

防护手段适用场景注意事项
#{} 占位符所有参数值传递默认首选方案
动态 SQL 标签条件查询、批量操作自动安全处理
${} + 白名单动态表名/列名必须严格校验输入
预编译语句所有数据库操作MyBatis 默认启用
输入过滤业务层参数校验补充防线,非唯一手段

重要提示:MyBatis 的防注入能力 高度依赖开发者的正确使用。避免以下致命错误:

  • 在注解或 XML 中混用 ${} 与用户输入;

  • 动态排序字段(ORDER BY ${field})未校验;

  • 存储过程内部拼接 SQL 未转义。

通过结合预编译机制、严格的 ${} 管控和业务层校验,可构建稳固的 SQL 注入防护体系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tsxchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值