PrepareStatement可以防止sql注入
预编译
select*from tablename where username=? and password=?
mybatis是如何防止SQL注入的
【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,
是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很
熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备
好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效
率。原因是SQL已编译好,再次执行时无需再编译
<select id="selectByNameAndPassword"
parameterType="java.util.Map" resultMap="BaseResultMap">
select id, username, password, role
from user
where username = #{username,jdbcType=VARCHAR}
and password = ${password,jdbcType=VARCHAR}
</select>
#和$的区别:
1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引
号。
如:where username=#{username},如果传入的值是111,那么解析成sql
时的值为where username="111", 如果传入的值是id,则解析成的sql为
where username="id".
2、$将传入的数据直接显示生成在sql中.
如:where username=${username},如果传入的值是111,那么解析成sql
时的值为where username=111;
如果传入的值是;drop table user;,则解析成的sql为:select id,
username, password, role from user where username=;drop table
user;
3、#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
4、$方式一般用于传入数据库对象,例如传入表名.
5、一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手
工地做好过滤工作,来防止sql注入攻击。
6、在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从
而不能避免注入攻击。但涉及到动态表名和列名时,只能使用
“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行
处理来防止注入。
【结论】在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。
若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL
注入攻击。