什么是SQL注入以及如何处理SQL注入问题

1、什么是SQL注入

SQL注入是一种注入攻击,可以执行恶意SQL语句,它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制WEB应用程序后面的数据库服务器,攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或WEB应用程序的身份验证和授权,并检索中整个SQL数据库的内容;还可以使用SQL注入来添加、修改和删除数据库中的记录。
简单来说:SQL注入是一种将SQL代码添加到输入参数中,传递到SQL服务器解析并执行的一种攻击手法,输入参数未经过过滤,直接拼接到SQL语句中,解析执行,达到预想之外的行为。

2、#{}如何防止SQL注入

(1)parameterType: 在映射文件中通过parameterType指定输入参数的类型
(2)resultType: 在映射文件中通过resultType指定输出结果的类型
(3)${}和#{}

1)#{}

  • #{}表示一个占位符。#{}接收输入参数,类型可以是简单类型、pojo、hashMap,如果接收简单类型,#{}中可以写成value或其他名称
  • 为什么用#{}而不用?代表占位符

因为框架将SQL和程序代码分开,所以无法直接确认参数的含义

  • #{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性的方式获取对象属性值

2)${}

  • ${}表示一个拼接符号,会引起SQL注入,所以不建议使用
  • ${}接收输入参数,类型可以是简单类型、pojo、hashmap,如果接收简单类型,${}中只能写成value
  • ${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性的方式获取对象属性值

注意: 如果我们传递过来的参数只是一个简单类型(例如String、Integer等,并没有封装多个属性的叫做简单类型,而封装多个属性并且提供了setter和getter的叫做封装类型。Map是封装类型,取值可以根据key取值),并且有多个#{}(名称可以任取),那么这里所有#{}占位符的最终获取值都相同。
一般${}用在我们能够确定值的地方,也就是我们程序员自己赋值的地方,而#{}一般用在用户输入值的地方

  • 默认情况下,使用#{}语法,Mybatis会产生PreparedStatement语句中,并且安全的设置PreparedStatement参数,这个过程中Mybatis会进行必要的安全检查和转义
  • #相当于对数据加上双引号,$相当于直接显示数据

综上,${}方式会引发SQL注入的问题,同时也会影响SQL语句的预编译,所以从安全性和性能的角度出发,应尽量使用#{}
${}在什么情况下使用呢?

  • 有时候可能需要直接插入一个不做任何修改的字符到SQL语句中,这个时候可以使用${}

【重要:】
Mybatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己动手编写,这和个时候当然要防止SQL注入。其实,Mybatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构。如下:


想防止SQL注入,理所当然的要在输入参数上下功夫,上面SQL传入参数后,打印出执行的SQL语句,会看到是这样的:

select id,title,author,content from blog where id= ?

不管输入什么参数,打印出的SQL都是这样的,因为Mybatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译,执行时,直接使用编译好的SQL,替换占位符?就可以了,因为 SQL注入只能对编译过程起作用 ,所以这样的方式就能很好的避免SQL注入的问题。
在Mybatis中,${}这样格式的参数会直接参与SQL编译,从而不能避免注入攻击 。但涉及到动态表名和列名时,只能使用${}这样的参数格式,所以这样的参数需要我们在代码中手工进行处理来防止注入。

【底层实现原理】
Mybatis是如何做到SQL预编译的呢?
其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,他的对象包含了编译好的SQL语句,这种准备好的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需在编译。

什么是SQL注入以及如何处理SQL注入问题_第1张图片

你可能感兴趣的:(mybatis,数据库,java,Mybatis,SQL注入,#{},${})