面试必知 mybatis防止sql注入

一.什么是sql注入:

用户通过表单提交的方式,填入与sql注释或者or 1=1等内容实现sql注入

二.JDBC防止sql注入

1.如果生成statement对象来实现凭借字符串是会被sql注入的。

 concat sqlString sql = "SELECT * FROM users WHERE name ='"+ name + "'";
 Statement stmt = connection.createStatement();
 ResultSet rs = stmt.executeQuery(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.mybatis可以通过xml文件或者注解的方式执行sql语句
1).XML文件:

<select id="getById" resultType="org.example.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);
}

2.mybatis提供两种方式进行参数替换( #{} 和 ${})
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="org.example.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="org.example.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="org.example.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="org.example.User">    
    <bind name="pattern" value="'%' + name + '%'" />   
     SELECT * FROM user    WHERE name LIKE #{pattern}
     </select>
    

    或者使用concat标签

    <select id="getUserListLikeConcat" resultType="org.example.User">    
    SELECT * FROM user WHERE name LIKE concat ('%', #{name}, '%')
    </select>
    
  2. in条件
    使用 < foreach> 和 #{}

    <select id="selectUserIn" resultType="com.example.User">  
    SELECT * FROM user WHERE name in  
    <foreach item="name" collection="nameList" open="(" separator="," close=")">        
    	#{name}  
    </foreach>
    </select>
    
  3. limit语句
    直接通过#{}防止sql注入

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值