Mybatis是如何实现SQL防注入的

Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$#的区别,它们的区别是使用#可以防止SQL注入,今天就来看一下它是如何实现SQL注入的。

什么是SQL注入

在讨论怎么实现之前,首先了解一下什么是SQL注入,我们有一个简单的查询操作:根据id查询一个用户信息。它的sql语句应该是这样:select * from user where id =。我们根据传入条件填入id进行查询。

如果正常操作,传入一个正常的id,比如说2,那么这条语句变成select * from user where id =2。这条语句是可以正常运行并且符合我们预期的。

但是如果传入的参数变成‘‘ or 1=1,这时这条语句变成select * from user where id = ‘‘ or 1=1。让我们想一下这条语句的执行结果会是怎么?它会将我们用户表中所有的数据查询出来,显然这是一个大的错误。这就是SQL注入。

Mybatis如何防止SQL注入

在开头讲过,可以使用#来防止SQL注入,它的写法如下:

<select id="safeSelect" resultMap="testUser">
   SELECT * FROM user where id = #{id}
</select>

在mybatis中查询还有一个写法是使用$,它的写法如下:

<select id="unsafeSelect" resultMap="testUser">
   select * from user where id = ${id}
</select>

当我们在外部对这两个方法继续调用时,发现如果传入安全的参数时,两者结果并无不同,如果传入不安全的参数时,第一种使用#的方法查询不到结果(select * from user where id = ‘‘ or 1=1),但这个参数在第二种也就是$下会得到全部的结果。

并且如果我们将sql进行打印,会发现添加#时,向数据库执行的sql为:select * from user where id = ‘ \‘\‘ or 1=1 ‘,它会在我们的参数外再加一层引号,在使用$时,它的执行sql是select * from user where id = ‘‘ or 1=1

弃用$可以吗

我们使用#也能完成$的作用,并且使用$还有危险,那么我们以后不使用$不就行了吗。

并不是,它只是在我们这种场景下会有问题,但是在有一些动态查询的场景中还是有不可代替的作用的,比如,动态修改表名select * from ${table} where id = #{id}。我们就可以在返回信息一致的情况下进行动态的更改查询的表,这也是mybatis动态强大的地方。

如何实现SQL注入的,不用Mybatis怎么实现

其实Mybatis也是通过jdbc来进行数据库连接的,如果我们看一下jdbc的使用,就可以得到这个原因。

#使用了PreparedStatement来进行预处理,然后通过set的方式对占位符进行设置,而$则是通过Statement直接进行查询,当有参数时直接拼接进行查询。

所以说我们可以使用jdbc来实现SQL注入。

看一下这两个的代码:

public static void statement(Connection connection) {
  System.out.println("statement-----");
  String selectSql = "select * from user";
  // 相当于mybatis中使用$,拿到参数后直接拼接
  String unsafeSql = "select * from user where id = '' or 1=1;";
  Statement statement = null;
  try {
    statement = connection.createStatement();
  } catch (SQLException e) {
    e.printStackTrace();
  }
  try {
    ResultSet resultSet = statement.executeQuery(selectSql);
    print(resultSet);
  } catch (SQLException e) {
    e.printStackTrace();
  }
  System.out.println("---****---");
  try {
    ResultSet resultSet = statement.executeQuery(unsafeSql);
    print(resultSet);
  } catch (SQLException e) {
    e.printStackTrace();
  }
}

public static void preparedStatement(Connection connection) {
  System.out.println("preparedStatement-----");
  String selectSql = "select * from user;";
  //相当于mybatis中的#,先对要执行的sql进行预处理,设置占位符,然后设置参数
  String safeSql = "select * from user where id =?;";
  PreparedStatement preparedStatement = null;
  try {
    preparedStatement = connection.prepareStatement(selectSql);
    ResultSet resultSet = preparedStatement.executeQuery();
    print(resultSet);
  } catch (SQLException e) {
    e.printStackTrace();
  }
  System.out.println("---****---");
  try {
    preparedStatement = connection.prepareStatement(safeSql);
    preparedStatement.setString(1," '' or 1 = 1 ");
    ResultSet resultSet = preparedStatement.executeQuery();
    print(resultSet);
  } catch (SQLException e) {
    e.printStackTrace();
  }
}

public static void print(ResultSet resultSet) throws SQLException {
  while (resultSet.next()) {
    System.out.print(resultSet.getString(1) + ", ");
    System.out.print(resultSet.getString("name") + ", ");
    System.out.println(resultSet.getString(3));
  }
}

总结

  • Mybatis中使用#可以防止SQL注入,$并不能防止SQL注入
  • Mybatis实现SQL注入的原理是调用了jdbc中的PreparedStatement来进行预处理。

    本文由博客一文多发平台 OpenWrite 发布!
    博主邮箱:[email protected],有问题可以邮箱交流。

原文地址:https://www.cnblogs.com/lnj96/p/12157911.html

时间: 2024-10-25 19:35:00

Mybatis是如何实现SQL防注入的的相关文章

sql 防注入 维基百科

http://zh.wikipedia.org/wiki/SQL%E8%B3%87%E6%96%99%E9%9A%B1%E7%A2%BC%E6%94%BB%E6%93%8A SQL攻击(SQL injection,台湾称作SQL资料隐码攻击),简称注入攻击,是发生于应用程序之数据库层的安全漏洞.简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏. 有部份人认为SQL注入攻击是只针对Mi

ASPSecurity SQL 防注入

<% '************** ASPSecurity SQL 防注入************** ' Copyright 2006 ' Create:2006-4-06 ' Update:2006-6-01 '*************************************************** If Request.Form<>"" Then StopInjection(Request.Form) If Request.QueryString

php sql防注入

没有太多的过滤,主要是针对php和mysql的组合.一般性的防注入,只要使用php的 addslashes 函数就可以了. 以下是一段copy来的代码: PHP代码 $_POST = sql_injection($_POST); $_GET = sql_injection($_GET); function sql_injection($content) { if (!get_magic_quotes_gpc()) { if (is_array($content)) { foreach ($con

.net 过滤 sql防注入类,省地以后每次都要重新弄!

/// <summary>    /// 过滤不安全的字符串    /// </summary>    /// <param name="Str"></param>    /// <returns></returns>    public static string FilteSQLStr(string Str)    { Str = Str.Replace("'", "")

360提供的SQL防注入

<?php class sqlsafe { private $getfilter = "'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABA

.net sql 防注入 httpmodule

1 新建一个类,实现IHttpModule接口 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; namespace DotNet.Common.WebForm { /// <summary> /// 简单防止sql注入 /// &

最新天猫3轮面试题目:虚拟机+并发锁+Sql防注入+Zookeeper

天猫一面 自我介绍.项目介绍 Spring拦截器.实现了哪些方法?底层原理 AOP如何配置,底层原理.2种动态代理,aop注解实现,xml定义切面 Bean的作用域,单例模式是否线程安全?恶汉模式是否线程安全?bean如何结束生命周期? Spring事务种类,如何回滚,A方法调用B方法,在B方法中出现异常,会回滚吗?(动态代理) 快速排序时间复杂度 JVM内存结构详细分配,各比例是多少 讲讲dubbo,数据库主从复制,2个节点读写分离,如何在读节点马上读到主节点写入的值 springboot和s

C# SQL防注入

string sql = "select * from student where id like" +"@key";Sqlconnection con = new Sqlconnetion();Sqlcommand com =new Sqlcommand();SqlParameter prmid = new SqlParameter();prmid.ParameterName = "@key";prmid.Value=key;com.Param

php-sql-parser sql防注入脚本

<?php /** * SQL Parser from: http://code.google.com/p/php-sql-parser/ * License: New BSD */ class PHPSQLParser { var $reserved = array(); var $functions = array(); function __construct($sql = false) { #LOAD THE LIST OF RESERVED WORDS $this->load_res