摘录之:
https://blog.csdn.net/bwh0520/article/details/80102040
mybatis是如何避免sql注入攻击的呢?
假设mapper文件为:
<select id="getNameByUserId" resultType="String"> SELECT name FROM user where id = #{userId} </select>
对应的java文件为:
public interface UserMapper{ String getNameByUserId(@Param("userId") String userId); }
可以看到输入的参数是String类型的userId,当我们传入userId="34;drop table user;"后,打印的语句是这样的:
select name from user where id = ?
不管输入何种userID,他的sql语句都是这样的。这就得益于mybatis在底层实现时使用预编译语句。数据库在执行该语句时,直接使用预编译的语句,然后用传入的userId替换占位符?就去运行了。不存在先替换占位符?再进行编译的过程,因此SQL注入也就没有了生存的余地了。
那么mybatis是如何做到sql预编译的呢?其实框架底层使用的正是PreparedStatement类。PreparedStaement类不但能够避免SQL注入,因为已经预编译,当N次执行同一条sql语句时,节约了(N-1)次的编译时间,从而能够提高效率。
如果将上面的语句改成:
<select id="getNameByUserId" resultType="String"> SELECT name FROM user where id = ${userId} </select>
当我们输入userId="34;drop table user;"后,打印的语句是这样的:
select name from user where id = 34;drop table user;
此时,mybatis没有使用预编译语句,它会先进行字符串拼接再执行编译,这个过程正是SQL注入生效的过程。
因此在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。
原文地址:https://www.cnblogs.com/20158424-hxlz/p/8972309.html
时间: 2024-10-16 08:55:23