JDBC之古老的SQL注入

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();
        }
    }
}
posted @ 2020-08-20 22:18  小熊猫陈江一  阅读(134)  评论(0编辑  收藏  举报