MyBatis中传参时为什么要用#{},这个问题和MyBatis如何防止SQL注入类似。不过在解释这个问题之前,先解释一下什么是SQL注入,还有些称作注入攻击这个问题。

  SQL注入就是SQL 对传入参数的拼接。sql语句是 String类型的,如果用  +  来拼接,表示的是直接操作这个String 类型的字符串,这是改变了sql的具体内容了,如果用#{id},表示的是操作字改变里面字段的参数值。

例如:

  • 用+拼接的: "select * from user where code="+code+ " and password="+password;

    那么code = “1233 or code=456”  password="2123":

  结果:  select * from user where code='123' or  code='456' and password=‘2123’那么这个sql的规则就乱了。

  • 用#操作的 select * from user where code=#{code} and password=#{password};

那么code = “1233 or code=456”  password="2123":

  结果:  select * from user where code=' 1233 or code=456 ' and password='2123'那么这个sql的规则还是老样子。

  综上所述就是会发生拼接错误!其实应该是参数传递出现的问题,#{}传递参数时,会在传递的参数上加上引号,在传递属性比如   password=? 时,可以很方便的使用#{password}。#{}传递的参数实际上是通过占位符(类似于JDBC中的?,在JDBC中会利用?去代替参数先进行编译,然后代入参数执行,这样就可以避免注入,因为注入不安全因素是发生在编译期,用占位符后就避免了这个问题)去传入到已经预编译好的SQL中去的,所以此时的SQL已经完成编译,只需要传参数就完成执行了。如:

1 <select id =“ getBlogById ”resultType =“ Blog ”parameterType =“ int ”>
2         SELECT id,title,author,content
3 FROM blog
4 WHERE id =#{id}
5 </select>

  在这里的id传参就是使用了#{},这部分打印后会看到的SQL语句是:

1 SELECT id,title,author,content FROM blog WHERE id =?

  就是不管输入什么参数打印出的SQL都是这样的。这是因为MyBatis的启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译,执行时,直接使用编译好的SQL ,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。

  具体可以看底层实现:其原理就是采用了JDBC的PreparedStatement。就会将sql语句:“select id,no from user where id =?” 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该SQL语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如select,from,where,and,or,order by等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了,因为这些SQL命令的执行,必须先得通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为SQL命令来执行的,只会被当做字符串字面值参数。所以的sql语句预编译可以防御SQL注入。而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

  同样的,想要避免SQL注入,只能使用上述的#{}结构,在MyBatis中,还有一种结构是${},使用该结构就不会避免注入。因为${}不会添加引号,传递的是什么就会直接放到SQL中去执行。

  简单滴说:# {}是经过预编译的,是安全的 ;$ {}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。

参考:

  1. https://www.cnblogs.com/jy107600/p/7097983.html
  2. https://bbs.csdn.net/topics/391069848
  3. https://blog.csdn.net/weixin_40773255/article/details/80426307
  4. https://blog.csdn.net/weixin_39986856/article/details/83651847

MyBatis中传参时为什么要用#{}的更多相关文章

  1. Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'

    Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String' 一.发现问题 <select ...

  2. mybatis中传集合时 报异常 invalid comparison: java.util.Arrays$ArrayList and java.lang.String

    犯了一个低级的错误,在传集合类型的参数时,把他当成字符串处理了,导致报类型转换的错误 把  and nsrsbh!=' ' 删掉就行了

  3. C++ 传参时传内置类型时用传值(pass by value)方式效率较高

    来源:唐磊的个人博客<C++ 传参时传内置类型时用传值(pass by value)方式效率较高> 在<Effective C++>里提到对内置(C-like)类型在函数传参时 ...

  4. URL传参时中文参数乱码的解决方法

    URL传参时,中文参数乱码的解决: 今天在工作中遇到了这样的一个问题,在页面之间跳转时,我将中文的参数放入到url中,使用location进行跳转传参,但是发现接收到的参数值是乱码.我的代码是这样写的 ...

  5. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  6. Hutool工具里,POST方法,body中传参的几种调用方法

    接口说明: POSTMAN测试: JAVA代码: package com.provy.guard.api; import java.util.HashMap; import java.util.Map ...

  7. Mybatis 中在传参时,${} 和#{} 的区别

    介绍 MyBatis中使用parameterType向SQL语句传参,parameterType后的类型可以是基本类型int,String,HashMap和java自定义类型. 在SQL中引用这些参数 ...

  8. Mybatis中使用 #{} 和 ${} 向sql传参时的区别

    今天在工作时,使用MyBatis中向sql传递两个参数时,一直显示SQL语法错误,仔细检查,才发现传入的参数被加上了引号,导致传入的参数(要传入的参数是表名)附近出现语法错误. 错误写法: } a } ...

  9. 关于SQL Server 2017中使用json传参时解析遇到的多层解析问题

    开发新的系统,DB部分使用了SQL Server从2016版开始自带的Json解析方式. 用了快半年,在个人项目,以及公司部分项目上使用了,暂时还没遇到大的问题,和性能问题. 今天在解析Json的多级 ...

随机推荐

  1. CALL TRANSACTION 使用说明

    以调用事务VA03为例: 在程序中添加如下代码就可以实现  SET PARAMETER ID 'AUN' FIELD var. CALL TRANSACTION 'VA03' AND SKIP FIR ...

  2. mysql5.5 升级至5.7

    mysql5.5 升级至5.7 1.下载mysql5.7.32 官方下载地址 解压 tar xvf mysql.tar.gz mysql/ 2. 进入旧的mysql的bin目录下导出mysql的数据 ...

  3. (17)-Python3之--文件操作

    1.文件的操作流程 第一,建立文件对象. 第二,调用文件方法进行操作. 第三,不要忘了关闭文件.(文件不关闭的情况下,内容会放在缓存,虽然Python会在最后自动把内容读到磁盘,但为了以防万一,要养成 ...

  4. 列出HBASE所有表的相关信息,如表名、创建时间等。

    import java.io.IOException; import java.util.Collection; import java.util.Iterator; import org.apach ...

  5. Fixing SQL Injection: ORM is not enough

    Fixing SQL Injection: ORM is not enough | Snyk https://snyk.io/blog/sql-injection-orm-vulnerabilitie ...

  6. Lambda架构正是这样一种用来处理不能够直接实时计算问题的通用架构

    https://mp.weixin.qq.com/s/BGHOw12iCASJy1pgkYZi3w 当数据处理做不到实时,应该怎么办?

  7. Linux 技巧:让进程在后台运行更可靠的几种方法

    Linux 技巧:让进程在后台运行更可靠的几种方法 https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/index.html 我们经常会碰到这 ...

  8. ThinkPHP3.2.4 order方法注入

    漏洞详情: 漏洞文件:./ThinkPHP\Library\Think\Db\Driver.class.php 中的 parseOrder方法: 这也是继上次order方法注入之后的修复手段. 可以看 ...

  9. (十)整合 JWT 框架,解决Token跨域验证问题

    整合 JWT 框架,解决Token跨域验证问题 1.传统Session认证 1.1 认证过程 1.2 存在问题 2.JWT简介 2.1 认证流程 2.2 JWT结构说明 2.3 JWT使用方式 3.S ...

  10. MVC与三层架构解析学习

    概要 MVC与三层架构不是简单的相等,二者之间存在一些区别. 今天,看到一位博主总结笔记,借鉴而来,以供以后学习. 将javaweb开发中的MVC(SSM框架)与三级架构比较,来解析二者之间的关系. ...