mybatis中#{}与 的 差 别 和 为 什 么 {}的差别和为什么 的差别和为什么{}可以防注入?
默认情况下,使用#{}语法,MyBatis会产生PreparedStatement语句中,并且安全的设置PreparedStatement参数,这个过程中MyBatis会进行必要的安全检查和转义。
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
$将传入的数据直接显示生成在sql中
MyBatis默认启用了预编译功能,在SQL执行前,会先将SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
在MyBatis中,在MyBatis中,由于 $ {} 这样格式的参数会直接参与SQL编译
,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用${}这样的参数格式
。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
有时候可能需要直接插入一个不做任何修改的字符串到SQL语句中。这时候应该使用${}语法。
比如,动态SQL中的字段名,如:ORDER BY ${name}
原理:
myBatis 对于#{} 在运行Sql 的时候,会将sql 语句解析成为?;对于 $ {} 则用本来的值进行替换。
myBatis 其实底层防止sql注入,使用的是prepareStatment语句。表现为#{name}和${name}的两种参数注入方法。
扩展:
在本人做项目中,所用到的$的情况不只是上面介绍的,还有如下:
当项目前端页面下拉多选时,该字段值为多个,传递到后台是
1,2,3,4
如上这种字符串,而该字段在数据库中是单值时,也需要使用 $。如下:
<if test="param.nameType != null and param.nameType != '' ">
and name_type in (${param.nameType})
</if>
当然,这可能与用到的前端框架有关。