Mybatis 注入
Mybatis 框架
Mybatis 是一个 java 持久层框架(Dao 层),用来连接 java 和关系型数据库,是执行 SQL 语句的帮手,不再需要使用 JDBC 连接
Mybatis 的使用有几个部分
核心配置 XML 文件:配置数据库地址、名字、密码等
Mybatis 工具类
java 实体类:普通的 java 对象,例如 User 类
Mapper 接口:定义的接口,写明需要执行的方法
XML 映射文件 Mapper.xml:这里会编写接口中方法对应的 SQL 语句,Mybatis 会自动解析这里的 SQL 语句,这里的语句需要在配置文件中注册
java 调用接口中的方法时,会自动到 XML 文件中获取 SQL 语句,然后发给数据库执行,将返回的数据包装成实体类返回
参数符号
Mybatis 的 SQL 语句需要手动编写,编写 XML 文件时,Mybatis 支持两种参数符号
#{}:使用预编译,将参数部分使用?替代,后续放入的参数不会进行 SQL 编译,而是当作字符串处理,可以避免 SQL 注入漏洞${}:使用的是拼接字符串,容易导致 SQL 注入漏洞
Mybatis 注入
Mybatis 框架的预编译会避免产生 SQL 注入漏洞,容易产生的有以下几种情况
模糊查询
在模糊查询中使用 #{} 传入参数会报错,如果修改为 ${} 就会产生 SQL 注入漏洞
<select id="getUsersByIds" resultType="User">
select * from users where username like '%${username}%'
</select>
修复的写法是使用 concat 连接
<select id="getUsersByIds" resultType="User">
select * from users where username like concat('%',#{username},'%')
</select>
动态多条件查询
查询多个 ID 时,可能会将一个用逗号分割的字符串传给 SQL,这里使用 in 语句,如果使用 #{},由于预编译机制,会导致将输入的当作一个字符串,不能满足需求,修改为了
<select id="getUsersByIds" resultType="User">
select * from users where username in (${ID})
</select>
修复的写法是将传来的字符在 java 层转化为 List 或 Array,使用 Mybatis 的 <foreach> 标签
<select id="getUsersByIds" resultType="User">
SELECT * FROM users WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
动态排序
动态排序功能,需要在 order by 后面传入参数,这里的参数是列名,JDBC 的规定,表名和列名是不能预编译的
<select id="getUsersSorted" resultType="User">
SELECT * FROM users ORDER BY ${column} limit 0,1
</select>
这里必须使用字符串拼接,所以 SQL 无法修改,需要在 Java 业务层添加白名单校验