欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaWeb学习十五(PreparedStatement)

程序员文章站 2024-03-11 14:03:07
...

一.PreparedStatement概述

  • 它是Statement接口的子接口
  • 强大之处:
    • 防SQL攻击
    • 提高代码的可读性,可维护性
    • 提高效率

1.什么是SQL攻击

在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的
SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!

2.演示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内的数据
JavaWeb学习十五(PreparedStatement)
对于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,所以查询出了所有的数据

JavaWeb学习十五(PreparedStatement)

这就是sql攻击,那怎么避免呢?这就需要用到今天所学的PreparedStatement了

3.创建PreparedStatement对象

我们先看看API吧

JavaWeb学习十五(PreparedStatement)

可以看到在获取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);
  }

4.PreparedStatement用法

  • 给出SQL模板
  • 调用Connection的PreparedStatement的preparedStatement(String sql模板)
  • 调用pstmt的setXxx()系列方法sql模板中的?赋值
  • 调用pstmt的executeUpdate()或executeQuery(),但它的方法都没有参数
@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