Mybatis 防止 sql 注入的原理

首先看一下 Mybatis 的查询过程:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1896ae05] was not registered for synchronization because synchronization is not active
==> Parameters: 1459(String)
2021-09-18 06:35:20.413 DEBUG 6 --- [nio-8080-exec-1] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
JDBC Connection [com.mysql.jdbc.JDBC4Connection@14aeb8db] will not be managed by Spring
==>  Preparing: select map_link from map_info where map_id=? limit 1;
<==      Total: 0
==> Parameters: 1458(String)
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@500b701f]

可以发现, Mybatis 先是开启了一次 SqlSession 查询,然后进行 Preparing,这个过程其实对应的就是 PreparedStatement,它做了一件核心的事情:将 SQL 执行语句和参数进行分离了

所谓分离,指的是 sql 执行语句和传入的参数是分开的,参数用占位符 ? 来代替。

接下来看一下 MySql 一次查询的原理过程(《高性能 MYSQL》)

MySQL执行一个查询的过程如图6-1所示:

  1. 在通信协议的支持下,客户端向MySQL服务器发送一条查询语句
  2. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果
  3. 否则,服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划
  4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询
  5. 将结果返回给客户端
    请添加图片描述

看一下 StackOverFlow 上的回答:

While in case of prepared statements we don’t alter our program, it remains intact

假设对于下列语句

$spoiled_data = "1; DROP TABLE users;"
$query        = "SELECT * FROM users where id=$spoiled_data";

其防注入的过程如下:

  1. 向 MySQL 发送一条查询语句,数据会被占位符的 ?的变量替换 。注意,该条查询被发送到服务器,其中是没有任何数据

    $db->prepare("SELECT * FROM users where id=?");
    
  2. 接着发送数据到 MySQL 服务器上。也就是这条命令,MySQL只会把他当成数据放到占位符上,里面即使有 SQL 命令并不会去执行,于是便防止了注入

    $db->execute($data);
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 有以下几种方法来防止 SQL 注入: 1. 使用参数化查询 MyBatis 推荐使用参数化查询来防止 SQL 注入。参数化查询使用 ? 或者 #{param} 来表示占位符,然后使用 PreparedStatement 进行预编译,将参数设置到占位符中,最后执行查询操作。这种方式可以避免用户输入的参数直接拼接到 SQL 语句中,从而防止 SQL 注入攻击。 示例: ``` <select id="getUserById" parameterType="int" resultType="User"> SELECT * FROM user WHERE id = #{id} </select> ``` 2. 使用动态 SQL MyBatis 的动态 SQL 可以根据条件动态生成 SQL 语句,避免拼接 SQL 语句时产生 SQL 注入漏洞。MyBatis 提供了多种动态 SQL 标签,如 if、choose、when、otherwise、foreach、set、trim、where、sql 等。 示例: ``` <select id="getUserList" parameterType="Map" resultType="User"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select> ``` 3. 使用 SQL 注入过滤器 MyBatis 可以通过插件来实现 SQL 注入过滤器,对于输入的参数进行过滤和转义,确保参数不会被注入SQL 语句中。 示例: ``` public class SqlInjectionPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); for (int i = 0; i < args.length; i++) { if (args[i] instanceof String) { args[i] = sqlInjectionFilter((String) args[i]); } } return invocation.proceed(); } private String sqlInjectionFilter(String param) { // 进行参数过滤和转义 return param; } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 配置属性 } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值