这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
前言
sql注入是一种通过在输入中注入sql语句,来达到攻击数据库的效果。今天使用Java语言,来分析一下sql注入的相关问题。
一、什么是SQL注入
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
二、模拟SQL注入
我们先创建一个简单的数据库和一个user表:
1 | sql复制代码create database test; |
我们在表中插入两个数据:
1 | sql复制代码insert into user values('zack', '123456'); |
我们再看一个简单的Java程序:
1 | java复制代码package com.zack.sql; |
我们看到code1,假设我们输入的如下:
1 | bash复制代码zack |
这个正好是与我们数据库中匹配的,那么code1中执行的sql语句如下:
1 | sql复制代码select * from user where username = 'zack' and password = '123456'; |
我们原本设想的是,如果输入不匹配的数据,将无法在数据库中查找到相应的东西,但是我们进行如喜爱输入:
1 | sql复制代码zack' or '1' = '1 |
这个时候,code1中执行的语句如下:
1 | sql复制代码select * from user where username = 'zack' or '1'='1' and password = '123456'; |
其中’1’ = ‘1’是恒为真的,所以这个sql语句不会再去判断密码是否正确,这样就完成了SQL注入攻击的效果。
三、如何防止SQL注入
防止sql注入的方法也非常简单,在jdbc中有一个sql语句预编译的对象,我们可以通过PrepareStatement类来实现。假设我们还是要执行查询操作,执行语句如下:
1 | sql复制代码String sql = "select * from user where username = ? and password = ?"; |
这里我们使用“?”来表示字段的值。然后我们来创建一个PrepareStatement对象,这里和Statement有些不一样:
1 | java复制代码//在创建PrepareStatement对象时,就传入了sql语句 |
这里是在创建PrepareStatement对象时就传入了sql语句,而Statement是在执行查询操作时才传入sql语句。
因为我们已经传入了sql语句,所以在执行查询时不需要传入sql语句,但是要多一步匹配参数的操作:
1 | java复制代码//将name的值替换到sql语句中第一个? |
其中name和pwd是我们输入的字符串变量。接下来我们就可以进行查询操作了:
1 | java复制代码ResultSet set = preStat.executeQuery(); |
这里操作和之前类似,只是不需要传入sql语句。完整代码如下:
1 | java复制代码package com.zack.sql; |
四、总结
SQL注入是早期比较流行的一种攻击数据库的方式,但现在很少会直接使用jdbc进行数据库操作,更不会直接使用sql语句拼接的方式进行操作。所以大多数情况SQL注入都是无效的,可能在一比较老的网址还是有效的,大家可以尝试以下。
本文转载自: 掘金