mybatis

#{}:相当于JDBC中的PreparedStatement 
$ {}:是输出变量的值 

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

MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,如果入参为#{}格式的,将入参替换编译好的SQL中的占位符“?”;如果入参格式为${},则直接使用编译好的SQL就可以了。因为SQL注入只能对编译过程起作用,所以使用#{}入参的方式可以很好地避免了SQL注入的问题。

SQL注入

两条SQL,入参id的值传入“1 or userId=2”,入参pwd的值传入“111111”。以#{}格式传入入参后的执行sql: 

select * from user where userId=”1 or userId=2” and password = “111111”; 

以${}格式传入入参后的执行SQL: 

select * from user where useId=1 or useId=2 and password = 111111;

很显然,以${}格式传入入参后的执行SQL打乱了我们的预期SQL格式及查询条件,从而实现SQL注入。所以,除了order by 等需要传入数据库字段等的入参使用${},其他的尽量使用#{}。

预编译之前的 SQL 语句已经不包含变量了,完全已经是常量数据了。相当于我们普通没有变量的SQL了。

综上所得, ${ } 变量的替换阶段是在动态 SQL 解析阶段,而 #{ }变量的替换是在 DBMS 中。


这是 #{} 和 ${} 我们能看到的主要的区别,除此之外,还有以下区别:

  • #方式能够很大程度防止SQL注入。
  • $方式无法防止SQL注入。
  • $方式一般用于传入数据库对象,例如传入表名.
  • 一般能用#的就别用$.

所以我们在使用mybatis的时候,尽量的使用#方式

mybatis中#{}和${}的区别

1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成SQL时的值为order by "111", 如果传入的值是id,则解析成的SQL为order by "id".
  
2. $将传入的数据直接显示生成在SQL中。如:order by $user_id$,如果传入的值是111,那么解析成SQL时的值为order by user_id,  如果传入的值是id,则解析成的SQL为order by id.
  
3. #方式能够很大程度防止sql注入。
  
4.$方式无法防止SQL注入。

5.$方式一般用于传入数据库对象,例如传入表名.
  
6.一般能用#的就别用$.

MyBatis排序时使用order by 动态参数时需要注意,用$而不是#

字符串替换
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用:
ORDER BY ${columnName}
这里MyBatis不会修改或转义字符串。

重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值