SQL注入攻击

1.用java实现登录的检查

package jdbc1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class Login {
    public static void main(String args[]){
        try(Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306","root","020809");
            Statement statement=connection.createStatement();
            Scanner scanner=new Scanner(System.in);){
            ResultSet resultSet = statement.executeQuery("select * from accounting_ledger.user where username='"+scanner.nextLine()+"'and password='"+scanner.nextLine()+"';");
            while(resultSet.next()){
                String name = resultSet.getString(1);
                System.out.println(name+"login successfully!");
                }
            }catch(Exception e){
            e.printStackTrace();
        }
    }
}

2.注入攻击

看似没有问题,可是如果我输入的如果是以下内容呢?

Test
1111' or 1=1; -- 

SQL注入攻击_第1张图片

这是因为我们实际运行的sql语句变成了

select * from user where username='Test' and pwd='1111' or 1=1; -- '

而1=1一定是对的,所以这个语句一定是正确的。我们发现,如果允许这样的数据插入,那么我们原有的SQL语句结构就遭到了破坏,使得用户能够随意登陆别人的账号。因此我们可能需要限制用户的输入来防止用户输入一些SQL语句关键字,但是关键字非常多,这并不是解决问题的最好办法。

PreparedStatement

package jdbc1;

import java.sql.*;
import java.util.Scanner;

public class safeLogin {
    public static void main(String args[]){
        try(Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306","root","020809");
            PreparedStatement statement = connection.prepareStatement("select * from user where username= ? and password=?;");
            Scanner scanner=new Scanner(System.in)){
            statement.setString(1, scanner.nextLine());
            statement.setString(2, scanner.nextLine());
            System.out.println(statement);    //打印查看一下最终执行的
            ResultSet resultSet = statement.executeQuery();
            while(resultSet.next()){
                String name = resultSet.getString(1);
                System.out.println(name+"login successfully!");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

我们发现,我们需要提前给到PreparedStatement一个SQL语句,并且使用?作为占位符,它会预编译一个SQL语句,通过直接将我们的内容进行替换的方式来填写数据。

而setString方法则会将读取的输入填入占位符的位置。第一个参数是传入的位置,第二个参数是传入的内容。

使用这种方式,我们之前的例子就失效了!我们来看看实际执行的SQL语句是什么: 

com.mysql.cj.jdbc.ClientPreparedStatement: select * from user where username= 'Test' and pwd='123456'' or 1=1; -- ';

我们发现,我们输入的参数一旦出现'时,会被变为转义形式\',而最外层有一个真正的'来将我们输入的内容进行包裹,因此它能够有效地防止SQL注入攻击! 

你可能感兴趣的:(sql,python,数据库)