3.Statement对象概述,以及Statement的弊端

Statement对象

1. 概述

在java.sql包中有三个接口分别定义了对数据库的调用的不同方式:

  • Statement:用于执行静态sql语句并返回结果
  • PreparedStatement:sql语句被预编译并存储在此对象中,可以使用此对象多次高效的执行该sql语句;
  • CallableStatement:用于执行存储过程。

2. Statement和PreparedStatement 的区别

  1. PreparedStatement 是 Statement的子类;
  2. Statement 是sql拼串,有sql注入的问题;
  3. PreparedStatement ,使用sql预编译,随后再填充占位符,解决了sql注入的问题;
  4. PreparedStatement 可以操作Blob类型的数据;
  5. PreparedStatement 可以批量操作;

3. Statement的弊端(sql注入攻击)

接下来用一个例子演示,数据表如下

java 复制代码
public class StatementTest {

    @Test
    public void test() throws Exception {
        Connection connection = JDBCUtils.getConnection();

        Statement statement = connection.createStatement();

        String username = "AA";
        String password = "123456";
        String sql = "SELECT user,password,balance FROM user_table WHERE USER = '" + username + "' AND PASSWORD = '" + password + "'";

        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()) {

            String user = resultSet.getString(1);
            String pwd = resultSet.getString(2);

            User user1 = new User(user, pwd);
            System.out.println(user1);

        }

        JDBCUtils.close(connection,statement);
    }
}

可以成功查询到数据:

java 复制代码
User{user='AA', password='123456', balance=1000}

但是如果修改一下输入信息:

java 复制代码
String username = "1' or ";
String password = " ='1' or '1' = '1";
java 复制代码
public class StatementTest {

    @Test
    public void test() throws Exception {
        Connection connection = JDBCUtils.getConnection();

        Statement statement = connection.createStatement();

        String username = "1' or ";
        String password = " ='1' or '1' = '1";
        String sql = "SELECT user,password,balance FROM user_table WHERE USER = '" + username + "' AND PASSWORD = '" + password + "'";
        
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()) {

            String user = resultSet.getString(1);
            String pwd = resultSet.getString(2);
            int balance = resultSet.getInt(3);

            User user1 = new User(user, pwd, balance);
            System.out.println(user1);

        }

        JDBCUtils.close(connection,statement);
    }
}

输出结果:将所有数据都查出来了

java 复制代码
User{user='AA', password='123456', balance=1000}
User{user='BB', password='654321', balance=1000}
User{user='CC', password='abcd', balance=2000}
User{user='DD', password='abcder', balance=3000}

相当于执行了以下sql

sql 复制代码
SELECT user,password,balance FROM user_table WHERE USER = '1' or ' AND PASSWORD = ' ='1' or '1' = '1'
相关推荐
2603_965148115 小时前
如何解析JSON数据?API返回的商品信息处理教程
开发语言·数据库·python·自动化·json·api
ltl5 小时前
RocksDB 经典故障排查:L0、compaction 与 write stall
数据库
xfhuangfu6 小时前
Oracle中建立到CDB和PDB的连接
数据库·oracle·rpc
小小龙学IT6 小时前
DuckDB 深度实战:用 C++ 在进程内跑一个「分析型数据库」
数据库·c++
NineData7 小时前
DTCC 2026 预告|NineData CEO& 创始人叶正盛:面向 AI Agent 的数据库 DevOps 与数据复制实践
数据库·人工智能·数据库开发·devops·ninedata·数据库技术·dtcc
J_bean7 小时前
MySQL 事务是否必须手动开启?
数据库·mysql·数据库事务·自动提交·手动提交
J_bean7 小时前
MySQL InnoDB 如何检测死锁、判定死锁、处理死锁
数据库·mysql·死锁·死锁检测·处理死锁·死锁判定
浪子明X8 小时前
从 MongoDB 文档到关系模型:构建可重跑、可对账的数据迁移流水线
数据库·mongodb·oracle
杜子不疼.8 小时前
国产数据库撑起固井软件自主化:金仓 × 中海油服「海恒 Cemsol」落地解析
数据库
隔窗听雨眠8 小时前
GBase 8s并发控制深度解析:封锁机制、隔离级别与死锁处理全攻略
服务器·数据库·oracle