Mybatis学习笔记:#{}占位符与${}字符串替换的区别?

1、#{}是预编译处理,$ {}是字符串替换

(1)#{} 表示一个占位符,采用preparedStatement给占位符设置值,自动进行java类型和jdbc类型转换,进行预编译处理,#{}可以有效防止sql注入(预编译是提前对SQL语句进行编译,而其后注入的参数将不会再进行编译)

(2)${} 表示字符串替换,通过${}可以将parameterType或实体 传入的内容拼接在sql中且不进行jdbc类型转换

举例说明二者区别,现在有如下SQL:

select count(1) from user where user_name = #{userName} and password = #{password}

说明:

使用#{}时,会进行jdbc类型转换,根据属性 自动加上单引号

select count(1) from user where user_name = 'admin' and password = '123456';

${}不会进行jdbc类型转换,只是简单的替换, 显然有语法错误,但是可以利用其进行sql注入

select count(1) from user where user_name = admin and password = 123456;

SQL注入举例说明

SQL注入就是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库执行一些恶意的操作。比如说:在登录过程中,利用上面的语句到数据库中查找用户名/密码是否存在,如果存在就登录成功,如果不存在就登录失败。

若使用${},恶意用户在表单中的用户名文本框中输入的是'admin'
密码框中输入的是 ' ' or 1 = 1 加了一引号和一个恒成立的条件,那么,传到数据库中的sql就是:

select count(1) from user where user_name = 'admin' and user_password = ' ' or 1=1

登录成功,该恶意用户是可以登录系统的! 这就是SQL注入,恶意攻击

而如果使用#{}是不会出现这种情况的,#{}默认会给输入的值加上引号,密码错误,登录失败:

//sql错误
select count(1) from user where user_name = ''admin'' and user_password ='' ' or 1=1'

既然有了#{}为什么还需要${}

#{}并不适用一些其他场景,比如要根据参数名动态排序,需要传入的参数是字段名,使用#{} 被解析成order by 'age' ,显然达不到排序目的。而此时就用到了${}进行字符串替换操作,即sql解析order by age;

你可能感兴趣的:(mybatis,mybatis)