JDBC-预防SQL注入-预处理对象PrepareStatement

PreparedStatement接口介绍

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

PreparedStatement特色

  • 由于有预先编译的功能, 提升SQL的执行效率
  • 能够有效的防止SQL注入的问题,安全性更高

获取PreparedStatement对象

Statement相似, 都是经过Connection进行建立建立sql

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);
    }
}

运行结果(正常)

image.png

运行结果(SQL注入)

image.png

这里提示登陆失败,也就是SQL注入的方式没有成功.
缘由是: 刚刚咱们使用了?做为占位符,那么在输入密码时,不管输入什么,其实都会总体以String形式赋值给sql语句.
因此这里最终的sql语句实际上是select * from test_02 where name = 'wdm' and password = "'0704' or '1' = '1' ". 很明显, 这个就不会返回正常结果数据库

PreparedStatement的执行原理

image.png

Statement与PrepareStatement的区别

  • Statement用于执行静态SQL语句,在执行时,必须指定一个事先准备好的SQL语句
  • PreparedStatement是预编译的SQL语句对象,语句中能够包含动态参数"?", 在执行时能够为"?"动态设置参数值
  • PreparedStatement能够减小编译次数提升数据库性能