⾯试必知mybatis防⽌sql注⼊
⼀.什么是sql注⼊:
⽤户通过表单提交的⽅式,填⼊与sql注释或者or 1=1等内容实现sql注⼊
⼆.JDBC防⽌sql注⼊
1.如果⽣成statement对象来实现凭借字符串是会被sql注⼊的。
concat sqlString sql ="SELECT * FROM urs WHERE name ='"+ name +"'";
Statement stmt = ateStatement();
ResultSet rs = uteQuery(sql);
2.解决办法:通过⽣成PreparedStatement 对象来防⽌sql注⼊
sql ="SELECT * FROM urs WHERE name= ? ";
PreparedStatement ps = connection.prepareStatement(sql);
/
/ 参数 index 从 1 开始
ps.tString(1, name);
3.存在的问题:⽐如 order by、column name,不能使⽤参数绑定
解决:此时需要⼿⼯过滤,如通常 order by 的字段名是有限的,因此可以使⽤⽩名单的⽅式来限制参数值
4.PreparedStatement 防⽌sql注⼊的原理:
⾸先通过sql语句通过占位符的⽅式执⾏sql语句,然后再把对应的参数替换上去,sql语句就只执⾏了⼀次,替换参数不会再执⾏sql语句。
三.mybatis防⽌sql注⼊
十二姻缘
1).XML⽂件:
<lect id="getById" resultType="ample.Ur">
我要听音乐
SELECT * FROM ur WHERE id = #{id}
</lect>
2).注解的⽅式
@Mapperpublic interface UrMapper {
@Select("SELECT * FROM ur WHERE id= #{id}")
Ur getById(@Param("id")int id);
}
1).使⽤ #{} 语法时,MyBatis 会⾃动⽣成 PreparedStatement ,使⽤参数绑定 ( ?) 的⽅式来设置值,上述两个例⼦等价的 JDBC 查询代码如下: 可以防⽌sql注⼊
String sql ="SELECT * FROM urs WHERE id = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.tInt(1, id);
2).使⽤${}其实就是进⾏sql的拼接,先进⾏sql的拼接再执⾏sql语句就会出现sql注⼊。
<lect id="getByName" resultType="ample.Ur">
SELECT * FROM ur WHERE name = '${name}' limit 1
</lect>彩虹小学
如果name 值为 ’ or ‘1’='1,实际执⾏的语句为
SELECT * FROM ur WHERE name = '' or '1'='1' limit 1
3).所以mybatis推荐使⽤#{}来防⽌sql注⼊。
3.同样的也会出现问题:⽐如 order by、column name,不能使⽤参数绑定
张姓取名其实就是如果需要⽤数据库表的字段来替换的话就不能⽤参数绑定
⽐如:
1). sortBy 参数值为 name ,如果使⽤#{}替换后会成为
ORDER BY "name"
即以字符串 “name” 来排序,⽽⾮按照 name 字段排序
2).所以需要使⽤${}来进⾏拼接,但是拼接就会出现sql注⼊:
代码层使⽤⽩名单的⽅式,限制 sortBy 允许的值,如只能为 name, email 字段,异常情况则设置为默认值 name 在 XML 配置⽂件中,使⽤ if 标签来进⾏判断
<lect id="getUrListSortBy" resultType="ample.Ur">
SELECT * FROM ur
<if test="sortBy == 'name' or sortBy == 'email'">
order by ${sortBy}
</if>
</lect>
因为 Mybatis 不⽀持 el,需要默认值的情况,可以使⽤ choo(when,otherwi)
<lect id="getUrListSortBy" resultType="ample.Ur">
SELECT * FROM ur
<choo>
一颗小桃树<when test="sortBy == 'name' or sortBy == 'email'">
order by ${sortBy}
</when>
<otherwi>
order by name
一亩地多少平米</otherwi>
</choo>
</lect>
4).mybatis更多场景:
1. 除了 orderby之外,还有⼀些可能会使⽤到 ${} 情况,可以使⽤其他⽅法避免,如
like语句
使⽤mybatis的bind标签
<lect id="getUrListLike" resultType="ample.Ur">
<bind name="pattern" value="'%' + name + '%'" />
SELECT * FROM ur WHERE name LIKE #{pattern}
</lect>
或者使⽤concat标签
<lect id="getUrListLikeConcat" resultType="ample.Ur">
SELECT * FROM ur WHERE name LIKE concat ('%',#{name}, '%')
</lect>
与马有关的成语2. in条件
使⽤ < foreach> 和 #{}
<lect id="lectUrIn" resultType="ample.Ur">
SELECT * FROM ur WHERE name in岳飞精忠报国
<foreach item="name" collection="nameList" open="(" parator="," clo=")">
#{name}
</foreach>
</lect>
3. limit语句
直接通过#{}防⽌sql注⼊