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. Python 日志打印之自定义logger handler

    日志打印之自定义logger handler By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #实践代码 handler.py #!/usr/bin/env ...

  2. 配置 containerd 镜像仓库完全攻略

    作者简介 王海龙,Rancher中国社区技术经理,负责Rancher中国技术社区的维护和运营.拥有6年的云计算领域经验,经历了OpenStack到Kubernetes的技术变革,无论底层操作系统Lin ...

  3. Flask扩展点总结(信号)

    信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 根据flask项目的请求流程来进行设置扩展点 1.中间件 from ...

  4. Java编程技术之浅析SPI服务发现机制

    SPI服务发现机制 SPI是Java JDK内部提供的一种服务发现机制. SPI->Service Provider Interface,服务提供接口,是Java JDK内置的一种服务发现机制 ...

  5. Dubbo 最基本的几个需求

    需求 http://dubbo.apache.org/zh-cn/docs/user/preface/requirements.html 在大规模服务化之前,应用可能只是通过 RMI 或 Hessia ...

  6. 目前 c++ primer学习总结笔记

    C++的开始 1 main的返回值:0为成功状态,非0为系统定义的错误类型 2 输入输出:计算结果为左侧运算对象,IO操作读写缓冲与程序中的动作无关 3 输入流istream对象:cin(标准输入): ...

  7. Vim配置及其他注意事项

    常用的一些配置 set t_ti= set t_te= "这两个比较特殊,后边说 set termencoding=utf-8 set encoding=utf-8 set fileenco ...

  8. 安装、登入centos7

    系统CentOS7.4 http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Everything-1708.iso 虚 ...

  9. Prometheus+Grafana通过kafka_exporter监控kafka

    Prometheus+Grafana通过kafka_exporter监控kafka 一.暴露 kafka-metric 方式 二.jmx_exporter方式 2.1 下载jmx_prometheus ...

  10. Spring框架——IOC&DI

    Spring Spring 目标 内容 Spring与web整合的原理 Spring 中包含的关键特性 Spring架构图 企业级框架 企业级系统 IOCDI IOC DI IOC和DI 为什么使用依 ...