乐趣区

关于jdbc:JDBC预防SQL注入预处理对象PrepareStatement

PreparedStatement 接口介绍

  • PreparedStatementStatement 接口的 子接口 , 继承于父接口中所有的办法. 它是一个 预编译 的 SQL 语句对象
  • 预编译 : 是指 SQL 语句被预编译, 并存储在PreparedStatement 对象中. 而后能够应用此对象屡次市郊地执行该语句

PreparedStatement 特点

  • 因为有事后编译的性能, 进步 SQL 的执行效率
  • 能够无效的避免 SQL 注入的问题, 安全性更高

获取 PreparedStatement 对象

Statement 相似, 都是通过 Connection 进行创立创立

Connection 接口中的办法 阐明
PreparedStatement prepareStatement(String sql) 指定预编译的 SQL 语句
  • 预编译的 SQL 语句: SQL 语句中应用 占位符?

PreparedStatement 接口罕用办法

  • Statement 相似, 接口罕用办法名都是 int executeUpdate()ResultSet executeQuery
  • Statement 不同, 上述两个办法是没有参数的. 因为在结构 PrepareStatement 对象时, 就曾经传入 SQL 进行了 预编译
罕用办法 阐明
int executeUpdate() 执行 insert / update / delete 语句. 返回受影响的行数
ResultSet executeQuery() 执行 select 语名. 返回后果集对象 Result

应用 PreparedStatement 的步骤

  • 编定 SQL 语句, 未知内容应用 ? 占位
    select * from test_02 where name = ? and password = ?
  • 获取 PreparedStatement 对象
  • 设置理论参数: 调用 setXxx 办法
  • 执行参数化 SQL
  • 敞开资源

应用 PreparedStatement 实现登录案例

代码示例

public class LoginTest02 {public static void main(String[] args) throws SQLException {

        // 1. 获取连贯
        Connection conn = JDBCUtils.getConnection();
        // 2. 应用占位符创立 sql 语句,获取 prepareStatement 对象
        // 应用?占位符的形式来设置参数
        String sql = "select * from test_02 where name = ? and password = ?";
        PreparedStatement preparedStatement = conn.prepareStatement(sql);
        // 3. 提醒用户输出用户名和明码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输出用户名:");
        String user = sc.next();
        System.out.println("请输出明码:");
        String pass = sc.next();
        // 4. 替换占位符,执行 sql 语句
        // 设置参数,应用 setXXX(int 占位符地位 从 1 开始, 要设置 / 替换的值)的办法设置占位符的参数
        preparedStatement.setString(1,user); // 设置第一个问号值为 name
        preparedStatement.setString(2,pass);
        ResultSet resultSet = preparedStatement.executeQuery();
        // 5. 处理结果集,判断是否登录胜利
        if(resultSet.next()){System.out.println("登录胜利!欢送:" + user);
        }else{System.out.println("登录失败!");
        }
        // 6. 敞开对象
        JDBCUtils.close(conn,preparedStatement,resultSet);
    }
}

运行后果(失常)

运行后果(SQL 注入)

这里提醒登录失败, 也就是 SQL 注入的形式没有胜利.
起因是: 刚刚咱们应用了? 作为占位符, 那么在输出明码时, 无论输出什么, 其实都会整体以 String 模式赋值给 sql 语句.
所以这里最终的 sql 语句其实是select * from test_02 where name = 'wdm' and password = "'0704' or '1' = '1' ". 很显著, 这个就不会返回失常后果

PreparedStatement 的执行原理

Statement 与 PrepareStatement 的区别

  • Statement用于执行动态 SQL 语句, 在执行时, 必须指定一个当时筹备好的 SQL 语句
  • PreparedStatement是预编译的 SQL 语句对象, 语句中能够蕴含动静参数 ”?”, 在执行时能够为 ”?” 动静设置参数值
  • PreparedStatement能够缩小编译次数进步数据库性能
退出移动版