mybatis--#{}与${}的区别

首先,谈谈mybatis怎么防止sql注入sql

<select id="selectUserInfo" resultType="com.test.vo.User" parameterType=”int”>
		SELECT
			tu.USER_ID as userId,
			tu.USER_NAME as userName
		FROM
			t_user tu
		WHERE
			tu.USER_ID = #{userId}
	</select>

上述是mybatis的mapping中一段代码,当请求的时候,控制台输出数据库

SELECT tu.USER_ID,tu.USER_NAME FROM t_user tu WHERE tu.USER_ID = ?

咱们会发现,不管输入什么参数,打印出的sql都是这样。缘由是:
mybatis启用了预编译功能,在SQL执行前,会将上面的sql发送给数据库进行编译;执行SQL的时候,直接使用预编译好的sql,传参替换占位符"?"就行。由于sql注入只能对编译过程起做用,所以,这种方式能够很好地避免sql注入问题。
mybatis底层实现原理
mybatis如何作到sql预编译?在底层框架的JDBC中的preparedStatement类起做用,该类的对象包含了许多编译好的SQL语句,这种预先编译的方式不只能提升安全性,并且在屡次执行同一个SQL的时候,可以提升效率,由于已经编译好的SQL,不须要再次编译了。
如今假设mybatis的mapping中的传参以下安全

WHERE
			tu.USER_ID = ${userId}

执行请求时,假设传参1000000000,打印出来的SQL是这样的mybatis

SELECT tu.USER_ID,tu.USER_NAME FROM t_user tu WHERE tu.USER_ID = 1000000000

结果发现传参直接显示出来,这样是没法阻止SQL注入的,在mybatis中,${xx}这种格式的参数是直接参与SQL编译,从而不能避免注入攻击。可是涉及到动态表名与列名时,只能使用${xx}这种格式参数。
总结:在编写mybatis映射语句时,尽可能采用#{xx}这样的格式。简单的理解#{}是通过预编译的,是安全的;而${}是直接编译,不安全的。
如今假设必须使用${}这种方式,则咱们须要手动的过滤一下内容(好比正则匹配等)。app

相关文章
相关标签/搜索