mybatis、mybatis-plus Sql注入

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

随着mybatis、mybatis-plus不断发展,目前已经成为市场流行的持久层框架,但是使用的过程中,使用不当的情况下还是可能会出现sql注入的风险,那么就简单的分析它们是如何来避免sql注入


一、SQL注入是什么?

SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的SQL语句中来改变查询结果,例如: OR 1=1 或者 ;drop table sys_user;等等

二、mybatis是如何做到防止sql注入的

mybatis中我们所写的sql语句都是在xml只能完成,我们在编写sql会用到 #{},${} 这个两个表达式。那 #{} 和 ${}两者之间有什么区别嘞?下面我将用两个SQL语句例子来进行说明。

<select id="selectUserByUserName" parameterType="java.lang.String" resultType="com.domain.UserInfo">
	SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER 
	<where>
		USER_ID= #{userName,jdbcType=VARCHAR} 
	</where> 
</select>
<select id="selectUserByUserName" parameterType="java.lang.String" resultType="com.domain.UserInfo">
	SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER 
	<where>
		USER_NAME= ${userName,jdbcType=VARCHAR} 
	</where> 
</select>

第一种SQL语句中使用的#{}方式,#{}中当传入的数据是字符串,会在使用" "双引号将值引起来,例如 userName 传入的值是 9;DROP TABLE SYS_USER;那么#{}去取后得到的结果就是 USER_NAME="9;DROP TABLE SYS_USER;"就算传入删除表的命令也不会被执行,因为9;DROP TABLE SYS_USER;会帮当成一个完成的字符串去进行值匹配。若使用第二种SQL${}方式取值,那就变成了USER_NAME=9;DROP TABLE SYS_USER; 因为 直 接 将 值 拼 接 在 S Q L 语 句 后 面 的 , 使 其 成 为 S Q L , 因 此 {}直接将值拼接在SQL语句后面的,使其成为SQL,因此 SQL使SQL{}是存在SQL注入的风险的,在使用时要注意手动处理。下面将会总结一下两者的区别。

1. #{} 和 ${} 两者的区别

  1. ‘#{}’:解析为一个 JDBC 预编译语句,一个‘ #{}’ 被解析为一个参数占位符 ? ,#{}方式将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。 如:WHERE USER_NAME =#{username},如果传入的值是9,那么解析成sql时的值为WHERE USER_NAME =“9”,如果传入的值是12345678,则解析成的sql为WHERE USER_NAME =“12345678”,
  2. ’ 仅 仅 为 一 个 纯 粹 的 s t r i n g 替 换 , {}’ 仅仅为一个纯粹的 string 替换, string{}方式传入的变量直接拼接在sql中。如:WHERE USER_NAME = ${username},如果传入的值是9,那么解析成sql时的值为WHERE USER_NAME =9; 如果传入的值是;DROP TABLE SYS_USER;,则解析成的sql为:SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER WHERE USER_NAME="9;DROP TABLE SYS_USER;所以象 ORDER BY 或者 GROUP BY 等可以使用 ${}方式。
  3. #{}方式底层采用预编译方式PreparedStatement,能够很大程度防止sql注入,因为SQL注入发生在编译时;$方式底层只是Statement,无法防止Sql注入。
  4. $方式一般用于传入数据库对象,例如传入表名

2.PreparedStatement和Statement的区别

① PreparedStatement 在执行sql命令时,命令会先被数据库进行解析和编译,然后将其放到命令缓存区,然后,当每一个执行的相同的sql 命令时,若在缓存区发了编译命令,就不会再次进行解析和编译,这样就可以进行重复使用。PreparedStatement 在编译是会将每个#{}标记符号解析为参数参数占位符?,传入的变量就是做为参数,不会对sql语句进行修改,这样就能防止SQL注入的攻击。‘’
②Statement是直接将Sql命令直接交给数据库进行运行,不能做到拦截SQL注入的攻击,因为SQL注入时发生在运行时。Statement每次都会对SQL命令进行解析和编译,增加大数据库的开销,因此它效率不如PreparedStatement。

3.什么是预编译

预编译是做些代码文本的替换工作。是整个编译过程的最先做的工作。处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。而SQL注入只能发生在运行时。

三、Mybatis-plus是如何做到防止sql注入的

四、参考内容

SQL预编译

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值