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语句变成了
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注入攻击!