什么是SQL注入?
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入地址域或页面请求的查询字符串中,欺骗服务器执行恶意的SQL命令。
mybatis防止SQL注入:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog
WHERE id=#{id}
</select>
打印执行的SQL语句,会看到SQL是这样的:
select id,title,author,content from blog where id=?
这是因为mybatis启动了预编译功能,在SQL执行前,会先将上面的SQL发送到数据库进行编译,执行时,直接使用编译好的SQL,替换占位符"?"就可以了。
【底层实现原理】mybatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。
内联参数的格式由“#{xxx}”变为了“${xxx}”
<select id="orderBlog" resultType="Blog" parameterType=”map”>
SELECT id,title,author,content
FROM blog
ORDER BY ${orderParam}
</select>
打印执行的SQL语句,会看到SQL是这样的:
SELECT id,title,author,content FROM blog ORDER BY id
显然,这样是无法阻止SQL注入的。在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
【结论】在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作(如判断一下输入的参数的长度是否正常(注入语句一般很长)),来防止SQL注入攻击。
hibernate如何进行防止SQL注入
1.对参数名称进行绑定:
Query query=session.createQuery(hql);
query.setString(“name”,name);
2.2.对参数位置进行绑定定:
Query query=session.createQuery(hql);
query.setString(0,name1);
query.setString(1,name2);
3.setParameter()方法:
Query query=session.createQuery(hql);
query.setParameter(“name”,name,Hibernate.STRING);
4.setProperties()方法:
Entity entity=new Entity();
entity.setXx(“xx”);
entity.setYy(100);
Query query=session.createQuery(“from Entity c where c.xx=:xx and c.yy=:yy ”);
query.setProperties(entity);
5.HQL拼接方法,这种方式是最常用,而且容易忽视且容易被注入的,通常做法就是对参数的特殊字符进行过滤,推荐大家使用 Spring工具包的StringEscapeUtils.escapeSql()方法对参数进行过滤:
public static void main(String[] args) {
String str = StringEscapeUtils.escapeSql("'");
System.out.println(str);
}