常见的SQL注入
- 数字注入
在浏览器地址栏输入:test.com/sql/article.php?id=1,这是请求方式为get的接口,发送这个请求相当于调用一个查询语句
$sql = "select * from article where id = ",$id
正常情况下,应该返回id=1的文章信息,但是,如果在浏览器地址栏输入test.com/sql/article.php?id=-1 OR 1 = 1,这就是一个SQL注入攻击了,可能会返回所有文章的相关信息。产生这种情况的原因是,id=-1 永远是false,1=1永远是true,所以整个where语句永远是true,相当于没有加where条件,所以查询的条件相当于是整张表的内容
- 字符串注入
常见的用户登录场景:输入用户名和密码,提交。
这是一个post请求,登录时调用接口test.com/sql/login.html,sql的查询过程:首先连接数据库,然后后台对post请求参数中的用户名、密码进行参数校验。假如此时输入用户名和密码为user和123456,提交,相当于调用了以下的SQL语句:
select * from user where username = 'user' and pasword = '123456'
1)用户名输入:user'#
,密码随意输入,如:111,然后提交。此时SQL语句是:
select * from user where username = 'user'#' and assword = '111'
#
后面被注释了,实际执行的sql是:
select * from user where username = 'user'
2)用户名输入:user'--
,密码随意输入,如:111
select * from user where username = 'user'--' and assword = '111'
--
后面被注释了,实际执行的sql是:
select * from user where username = 'user'
PreparedStatement 防止SQL注入
- PreparedStatement是Statement的子接口,可以传入带占位符的SQL语句,并且提供了补充占位符变量的方法。
- PreparedStatement能最大可能提高性能:DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时,只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。但在Statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义,实事实是没有数据库会对普通语句编译后的执行代码缓存,这样每执行一次都要对传入的语句编译一次。
class MyTest{
// 更新 删除 添加
public void testPreparedStatement(){
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb";
Connection connection = null;
PreparedStatement preparedStatement = null;
try{
connection = DriverManager.getConnection(url,"root", "root");
String sql = "Insert into customers(name,email,birth) values(?,?,?)"
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"test");
preparedStatement.setString(2,"test@qq.com");
preparedStatement.setString(2,"test@qq.com");
preparedStatement.setDate(3,new Date(new java.util.Date().getTime()));
preparedStatement.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
preparedStatement.close();
connection.close();
}
}
// 查询
public void testPreparedStatement01(){
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "user";
String pasword = "123456"
String sql = "select * from users where username = ?" + "and password = ?"
Connection connection = null;
PreparedStatement preparesStatement = null;
ResultSet resultSet = null;
try{
conncection = DriverManager.getConnection(url,"root", "root");
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,username);
preparedStatement.setString(2,password);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("success");
}else{
System.out.println("fail");
}
}catch(Exception e){
e.printStackTrace();
}finally{
resultSet.close();
preparedStatement.close();
connection.close();
}
}
}