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
小白的才疏学浅的总结就到这里了,感谢各位的阅读
