SQL注入和Mybatis预编译防止SQL注入
什么是SQL注入??
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或页面请求url的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
实战举例
有个登陆框如下:
可以看到除了账号密码之外,还有一个公司名的输入框,根据输入框的形式不难推出SQL的写法如下:
SELECT * From table_name WHERE name=‘XX’ and password=‘YY’ and corporate=‘ZZ’
怎么做呢,?
因为没有校验,因此,我们账号密码,都不填写,直接在最后,添加 or 1=1 –
看看与上面SQL组合,成了如下:
SELECT * From table_name WHERE name=’’ and password=’’ and corporate=’’ or 1=1-’
从代码可以看出,前一半单引号被闭合,后一半单引号被 “–”给注释掉,中间多了一个永远成立的条件“1=1”,这就造成任何字符都能成功登录的结果。
重要提醒
不要以为在输入框做个检查就够了,不要忘记了,我们web提交表单,是可以模拟url直接访问过去,绕开前段检查。因此,必须是后端,或是数据来检查才能有效防止。
(1)检查用户输入的合法性;
(2)将用户的登录名、密码等数据加密保存。
(3)预处理SQL。
(4)使用存储过程实现查询,虽然不推荐,但也是一个方法。
MySQL预处理是怎么防止的呢?
MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。其实,MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,如下:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog
WHERE id=#{id}
</select>
这里,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中黄色高亮即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:
SELECT id,title,author,content FROM blog WHERE id = ?
不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。
话说回来,是否我们使用MyBatis就一定可以防止SQL注入呢?当然不是,请看下面的代码:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog
WHERE id=${id}
</select>
仔细观察,内联参数的格式由“#{xxx}”变为了“${xxx}”。如果我们给参数“id”赋值为“3”,将SQL打印出来是这样的:
SELECT id,title,author,content FROM blog WHERE id = 3
(上面的对比示例是我自己添加的,为了与前面的示例形成鲜明的对比。)
<select id="orderBlog" resultType="Blog" parameterType=”map”>
SELECT id,title,author,content
FROM blog
ORDER BY ${orderParam}
</select>
仔细观察,内联参数的格式由“#{xxx}”变为了“${xxx}”。如果我们给参数“orderParam”赋值为“id”,将SQL打印出来是这样的:
SELECT id,title,author,content FROM blog ORDER BY id
显然,这样是无法阻止SQL注入的。在MyBatis中,“${xxx}”
这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”
这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
【结论】在编写MyBatis的映射语句时,尽量采用“#{xxx}”
这样的格式。若不得不使用“${xxx}”
这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。
#{}:相当于JDBC中的PreparedStatement
${}:是输出变量的值
简单说,#{}是经过预编译的,是安全的;${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
如果我们order by语句后用了${}
,那么不做任何处理的时候是存在SQL注入危险的。你说怎么防止,那我只能悲惨的告诉你,你得手动处理过滤一下输入的内容。如判断一下输入的参数的长度是否正常(注入语句一般很长),更精确的过滤则可以查询一下输入的参数是否在预期的参数集合中。
SQL注入和Mybatis预编译防止SQL注入的更多相关文章
- [疯狂Java]JDBC:PreparedStatement预编译执行SQL语句
1. SQL语句的执行过程——Statement直接执行的弊病: 1) SQL语句和编程语言一样,仅仅就会普通的文本字符串,首先数据库引擎无法识别这种文本字符串,而底层的CPU更不理解这些文本字符串( ...
- 加载执行预编译的Sql :prepareStatement
1.获得连接:Connection con = null; con = DBUtil.getConnection(); 2.写sql语句:String sql=""; 3.用连接加 ...
- 借助预编译防止sql注入攻击
可重用的sql操作类 public ResultSet doQuery(String sql,Object[] params){ ResultSet rs = null; conn = this.ge ...
- PreparedStatement预编译的sql执行对象
一.预编译,防sql注入 其中,设置参数值占位符索引从1开始:在由sql 连接对象创建 sql执行对象时候传入参数sql语句,在执行对象在执行方法时候就不用再传入sql语句: 数据库索引一般是从1开始 ...
- mybatis深入理解之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- JDBC编程之预编译SQL与防注入
在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedS ...
- 如何预防SQL注入?预编译机制
1.预编译机制(一次编译多次执行,防止sql注入) 2.预编译机制
随机推荐
- Vue定义全局过滤器filter
这里介绍的是多个过滤器一起添加到全局中 1.创建方法 首先src下新建plugin文件夹,用来存放插件. 在plugin文件夹内新建filters.js,编写方法(如隐藏手机号码等等...) /** ...
- 详解PHP反序列化中的字符逃逸
首发先知社区,https://xz.aliyun.com/t/6718/ PHP 反序列化字符逃逸 下述所有测试均在 php 7.1.13 nts 下完成 先说几个特性,PHP 在反序列化时,对类中不 ...
- input框处理大全
1.去掉谷歌input记住账号或密码时默认出现的黄色背景: 直接用css的内阴影来覆盖黄色(代码中 white可换成其他颜色) input:-webkit-autofill { -webkit-box ...
- php header() 常用content-type
//定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Content-type: application/at ...
- Logon Trigger Example (C++)
This C++ example shows how to create a task that is scheduled to execute Notepad when a user logs on ...
- 消息中间件之zookper安装部署
消息中间件之zookper安装部署jdk可以在官网或者网上下载[root@q tools]# chmod 755 jdk-8u40-linux-x64.rpm [root@q tools]# rpm ...
- (数据科学学习手札82)基于geopandas的空间数据分析——geoplot篇(上)
本文示例代码和数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在前面的基于geopandas的空间数据分 ...
- C6 C7的开机启动流程
C6开机启动流程 1.内核引导,加电自检(通电后检查内核):检查bios的配置,检测硬件 装好系统之后才会进行以下内容 MBR 引导 (3.2.1...) GRUB菜单 (选择不同的系统)(按e,进入 ...
- Clustered和Nonclustered Indexes 各自得特点和区别及长短处
1 簇索引 簇索引对表的物理数据页中的数据按列进行排序然后再重新存储到磁盘上即簇索 引与数据是混为一体的它的叶节点中存储的是实际的数据由于簇索引对表中的数据一 一进行了排序因此用簇索引查找数据很快但由 ...
- 重识TCP/IP协议族与HTTP基础
不忘初心 砥砺前行, Tomorrow Is Another Day ! 本文概要: TCP/IP协议族的网络分层 TCP三次握手四次挥手 Http简介 报文结构 Http的请求方法及状态码 常用的H ...