SQL注入
产生SQL注入原因
用户输入的数据中有SQL关键字或语法并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一直得到正确的结果集。这种现象称为SQL注入。
Statement statement = connection.createStatement();
String sql = "select * from student where name='" + nam
+ " ' and password = ' " + psd + "'";
ResultSet resultSet1 = statement.executeQuery(sql);
System.out.println(sql);
/* connection.createStatement() 产生SQL注入
SQL注入,当用户输入非法的SQL语句,导致最后拼接的SQL语句失效,产生SQL注入
比如:输入 名字时 输入: xxx' or 1 = 1 # 输入密码任意输入
导致最后sql为:
select * from student where name='xxx' or 1 = 1 #' and password = 'xxx'
细看下这条语句,发现#后面的都被注释掉了,所以密码无论怎样输入都无关,
而前面的条件永远是 true,所以导致SQL注入
*/
如何避免SQL注入:
由于编写的SQL语句是在用户输入数据,整合数据后进行编译,所以为了使SQL语句在用户输入数据前就已经编译成完整的SQL语句,等用户输入数据后在进行填充数据。
使用connection.prepareStatement(sql)预加载SQL语句
String sql = "select * from student where name = ? and password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,nam);
preparedStatement.setString(2,psd);
ResultSet resultSet = preparedStatement.executeQuery();
System.out.println(sql);
System.out.println(preparedStatement.toString());
/*
而使用connection.prepareStatement(sql2)会预编译sql语句,当输入时非法字符时,
输入 名字时 输入: xxx' or 1 = 1 # 输入密码任意输入
输出sql语句:
select * from student where name = ? and password = ?;
preparedStatement.toString()语句:
select * from student where name = 'xxx\' or 1 = 1 #' and password = 'xxx';
preparedStatement 会将 ? 占位的地方 全都当作一个整体 ,所以 避免了SQL注入问题
*/
PreparedStatement注意点
概念:
PreparedStatement继承了Statement接口,执行SQL语句的方法没有差别。
作用:
- 1、预编译SQL语句,提高效率
- 2、安全,避免SQL注入
- 3、可以动态的填充数据,执行多个同构的SQL语句
应用:
- 1、JDBC中的所有参数都是由 ?符号占位的,这被称为参数标记
String sql = "select * from student where name = ? and password = ?";
- 2、在执行SQL语句之前,必须为每个参数提供值。
preparedStatement.setXxx(第几个?位置,"参数值");
preparedStatement.setString(1,nam);
preparedStatement.setString(2,psd);
防注入代码Demo
public class JDBCLogin {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("**********欢迎登录XXX系统**********");
System.out.println("请输入名字:");
String nam = input.nextLine();
System.out.println("请输入密码:");
String psd = input.nextLine();
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/gp2002";
Connection connection = DriverManager.getConnection(url, "root", "root");
/* 避免SQL注入,不建议再去使用
Statement statement = connection.createStatement();
String sql1 = "select * from student where name='"
+ nam + "' and password = '" + psd + "'";
ResultSet resultSet1 = statement.executeQuery(sql1);
System.out.println(sql1);
*/
String sql2 = "select * from student where name = ? and password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql2);
preparedStatement.setString(1,nam);
preparedStatement.setString(2,psd);
ResultSet resultSet2 = preparedStatement.executeQuery();
System.out.println(sql2);
System.out.println(preparedStatement.toString());
if (resultSet.next()) {
System.out.println("登录成功!!!");
} else {
System.out.println("登录失败,用户名或密码错误。。。");
}
resultSet2.close();
preparedStatement.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}