mybatis中#{}与${}的差别和为什么${}可以防注入?(面试过)

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>

当然,这可能与用到的前端框架有关。

展开阅读全文

没有更多推荐了,返回首页