MySQL 注入详解及其解决方法

今天刚刚看到MySQL注入

首先,先来了解一下,SQL注入到底是什么

在网上可以收到很多关于SQL注入的例子,我这里想说一下最 基本的。 1:最基本的查询 xml语句

select * from user where id = #{
          
   id};

查询接口:select 请求方式:GET 请求参数:id

@RequestMapping(value = "/select/{id}",
 method = RequestMethod.GET)

这就是一个最普通的,根据id查询user表中的id与输入的id对应的一行数据,同样这是一个简单的接口定义,但是存在SQL注入风险。

如果在浏览器输入

http://localhost:8080/select/1

发送这个请求相当于调用一个查询语句 正常情况下,应该返回一个id=1的文章信息。

但是存在问题: 当在浏览器输入时

http://localhost:8080/select/1=1

这就是一个SQL注入攻击了,可能会返回所有文章的相关信息。为什么会这样呢? 1=1永远是true,所有整个where语句永远是ture,所以where条件相当于没有加where条件,那么查询的结果相当于整张表的内容。

解决办法

那么有哪些方法可以解决这些问题呢?

1、严格检查输入变量的类型和格式

对于整数参数,加判断条件:不能为空、参数类型必须为数字

对于以上的xml语句:我们可以这么改写:

<select >
select * from user where 
 <if test="id != null and id != ">
      id = #{
          
   id}
 </if>
 //对id进行非空校验,如果为空会报错
</select>

同样的可以对接口编写进行修改

@RequestMapping(value = "/select/{id}", 
method = RequestMethod.GET)
    public HttpServletResponseselect(@PathVariable Integer id){
          
   
    //select 方法函数
    //参数里对 id,进行拦截,只允许int类型通过
}

对于字符串参数,可以使用正则表达式进行过滤:如:必须为[0-9a-zA-Z]范围内的字符串

2)过滤和转义特殊字符

在username这个变量前进行转义,对 、"、 等特殊字符进行转义,如:

userName = StringEscapeUtils.escapeSql(userName);

3)利用mysql的预编译机制

把sql语句的模板(变量采用占位符进行占位)发送给mysql服务器,mysql服务器对sql语句的模板进行编译,编译之后根据语句的优化分析对相应的索引进行优化,在最终绑定参数时把相应的参数传送给mysql服务器,直接进行执行,节省了sql查询时间,以及mysql服务器的资源,达到一次编译、多次执行的目的,除此之外,还可以防止SQL注入。具体是怎样防止SQL注入的呢?实际上当将绑定的参数传到mysql服务器,mysql服务器对参数进行编译,即填充到相应的占位符的过程中,做了转义操作。

这个就像我上面写的

select * from user where id = #{
          
   id};
//使用#{},#可以对id进行预编译
//而不能使用${},这是直接将${}里的值,赋值给id

小白的才疏学浅的总结就到这里了,感谢各位的阅读

经验分享 程序员 微信小程序 职场和发展