⾯试必知mybatis防⽌sql注⼊
sql语句替换表中内容⼀.什么是sql注⼊:
⽤户通过表单提交的⽅式,填⼊与sql注释或者or 1=1等内容实现sql注⼊
⼆.JDBC防⽌sql注⼊
1.如果⽣成statement对象来实现凭借字符串是会被sql注⼊的。
concat sqlString sql ="SELECT * FROM users WHERE name ='"+ name +"'";
Statement stmt = ateStatement();
ResultSet rs = uteQuery(sql);
2.解决办法:通过⽣成PreparedStatement 对象来防⽌sql注⼊
sql ="SELECT * FROM users WHERE name= ? ";
PreparedStatement ps = connection.prepareStatement(sql);
/
/ 参数 index 从 1 开始
ps.setString(1, name);
3.存在的问题:⽐如 order by、column name,不能使⽤参数绑定
解决:此时需要⼿⼯过滤,如通常 order by 的字段名是有限的,因此可以使⽤⽩名单的⽅式来限制参数值
4.PreparedStatement 防⽌sql注⼊的原理:
⾸先通过sql语句通过占位符的⽅式执⾏sql语句,然后再把对应的参数替换上去,sql语句就只执⾏了⼀次,替换参数不会再执⾏sql语句。
三.mybatis防⽌sql注⼊
1).XML⽂件:
<select id="getById" resultType="ample.User">
SELECT * FROM user WHERE id = #{id}
</select>
2).注解的⽅式
@Mapperpublic interface UserMapper {
@Select("SELECT * FROM user WHERE id= #{id}")
User getById(@Param("id")int id);
}
1).使⽤ #{} 语法时,MyBatis 会⾃动⽣成 PreparedStatement ,使⽤参数绑定 ( ?) 的⽅式来设置值,上述两个例⼦等价的 JDBC 查询代码如下: 可以防⽌sql注⼊
String sql ="SELECT * FROM users WHERE id = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1, id);
2).使⽤${}其实就是进⾏sql的拼接,先进⾏sql的拼接再执⾏sql语句就会出现sql注⼊。
<select id="getByName" resultType="ample.User">
SELECT * FROM user WHERE name = '${name}' limit 1
</select>
如果name 值为 ’ or ‘1’='1,实际执⾏的语句为
SELECT * FROM user 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 标签来进⾏判断
<select id="getUserListSortBy" resultType="ample.User">
SELECT * FROM user
<if test="sortBy == 'name' or sortBy == 'email'">
order by ${sortBy}
</if>
</select>
因为 Mybatis 不⽀持 else,需要默认值的情况,可以使⽤ choose(when,otherwise)
<select id="getUserListSortBy" resultType="ample.User">
SELECT * FROM user
<choose>
<when test="sortBy == 'name' or sortBy == 'email'">
order by ${sortBy}
</when>
<otherwise>
order by name
</otherwise>
</choose>
</select>
4).mybatis更多场景:
1. 除了 orderby之外,还有⼀些可能会使⽤到 ${} 情况,可以使⽤其他⽅法避免,如
like语句
使⽤mybatis的bind标签
<select id="getUserListLike" resultType="ample.User">
<bind name="pattern" value="'%' + name + '%'" />
SELECT * FROM user WHERE name LIKE #{pattern}
</select>
或者使⽤concat标签
<select id="getUserListLikeConcat" resultType="ample.User">
SELECT * FROM user WHERE name LIKE concat ('%',#{name}, '%')
</select>
2. in条件
使⽤ < foreach> 和 #{}
<select id="selectUserIn" resultType="ample.User">
SELECT * FROM user WHERE name in
<foreach item="name" collection="nameList" open="(" separator="," close=")">
#{name}
</foreach>
</select>
3. limit语句
直接通过#{}防⽌sql注⼊
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论