在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的
SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!
public boolean login(String username,String password) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String user="root";
String pass="T471912619";
String url="jdbc:mysql://localhost:3306/test1?serverTimezone=UTC";
Connection connection=DriverManager.getConnection(url, user, pass);
Statement statement=connection.createStatement();
String sql="SELECT *FROM t_user WHERE username='"+username+"' and password='"+password+"'";
System.out.println(sql);
ResultSet rs=statement.executeQuery(sql);
return rs.next();
}
@Test
public void fun1() throws ClassNotFoundException, SQLException {
boolean flag=login("zhangsan", "123");
System.out.println(flag);
}
控制台打印结果
true
对于表t_user内的数据
对于t_user表中的数据,把上面的login方法内的两个参数改成表内数据打印的都是true,反之,不是表中数据就是false
我们再看看下面吧
public boolean login(String username,String password) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String user="root";
String pass="T471912619";
String url="jdbc:mysql://localhost:3306/test1?serverTimezone=UTC";
Connection connection=DriverManager.getConnection(url, user, pass);
Statement statement=connection.createStatement();
String sql="SELECT *FROM t_user WHERE username='"+username+"' and password='"+password+"'";
System.out.println(sql);
ResultSet rs=statement.executeQuery(sql);
return rs.next();
}
@Test
public void fun1() throws ClassNotFoundException, SQLException {
String username="a' or 'a'='a";
String password="a' or 'a'='a";
boolean flag=login(username,password);
System.out.println(flag);
}
最终控制台打印的是true,为什么呢?我们看看这个sql语句吧
SELECT *FROM t_user WHERE username='a' or 'a'='a' and password='a' or 'a'='a'
false true false true
中间or所以为true 中间or所以为true
两个true所以为true
在看看数据库查询出来的效果,因为这条sql语句对每行数据都是true,所以查询出了所有的数据
这就是sql攻击,那怎么避免呢?这就需要用到今天所学的PreparedStatement了
我们先看看API吧
可以看到在获取Connection对象之前我们的步骤没有发生变化,所以我们来想想代码吧!
public boolean login(String username,String password) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String user="root";
String pass="T471912619";
String url="jdbc:mysql://localhost:3306/test1?serverTimezone=UTC";
Connection connection=DriverManager.getConnection(url, user, pass);
//sql模板
String sql="SELECT *FROM t_user WHERE username=? AND password=?";
//创建PreparedStatement对象
PreparedStatement pstmt=connection.prepareStatement(sql);
}
@Test
public void fun1() throws ClassNotFoundException, SQLException {
String username="a' or 'a'='a";
String password="a' or 'a'='a";
boolean flag=login(username,password);
System.out.println(flag);
}
public boolean login(String username,String password) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String user="root";
String pass="T471912619";
String url="jdbc:mysql://localhost:3306/test1?serverTimezone=UTC";
Connection connection=DriverManager.getConnection(url, user, pass);
//sql模板
String sql="SELECT *FROM t_user WHERE username=? AND password=?";
//创建PreparedStatement对象
PreparedStatement pstmt=connection.prepareStatement(sql);
//给参数赋值
pstmt.setString(1,username);//给第一个问号赋值
pstmt.setString(2,password);//给第二个问号赋值
ResultSet rs=pstmt.executeQuery();
return rs.next();
}
控制台打印
false
public void fun1() throws ClassNotFoundException, SQLException {
String username="zhangsan";
String password="123";
boolean flag=login(username,password);
System.out.println(flag);
}
控制台打印
true