SQL注入Statement与Preparement的区别

一般jdbc的执行流程

1.导包

2.加载驱动

     通过反射拿到Driver对象:

Class.forName("driver")

3.建立连接

Connection connection=DriverManager.getConnection();

4.获取statment对象或预加载preparement

5.通过对象调用增删改查方法,返回整型的受影响行数或返回结果集后处理结果集

6.关闭连接

关闭连接时应注意先开的后关

例如:

写一个关闭流的方法

 

复制代码
 public static void close(Connection connection, Statement statement, ResultSet resultSet){
        //先关后打开的
        //关闭ResultSet集合
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        //关闭statement对象
        if (statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //关闭connection连接
        if (connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
复制代码

statement与预加载preparement的区别

不使用预加载:

Statement statement = connection.createStatement();//获取statement对象

在调用增删改executeUpdate()方法或查询executeQuery()方法时传入相应的SQL语句

例如:

复制代码
public class Jdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.驱动地址
        String driver="com.mysql.jdbc.Driver";
        //2.url数据库地址
        String url="jdbc:mysql://localhost:3306/user?useSSL=false";
        //3.数据库的账号
        String username="root";
        //4.数据库的密码
        String password="123456";
        //5.加载驱动
        Class.forName(driver);
        //6.建立连接
        Connection connection = DriverManager.getConnection(url, username, password);
        //获取statement对象
        Statement statement = connection.createStatement();
}
复制代码

SQL注入

由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入。

在上面的一段代码中添加如下代码

复制代码
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String user = scanner.nextLine();
System.out.println("请输入密码:");
String pass = scanner.nextLine();
//查询SQl语句
String sql=" SELECT * from student1 WHERE student1.student_name=\'"+user+"\' and student1.login_pwd=\'"+pass+"\'";
//调用查询executeQuery()方法
ResultSet resultSet = statement.executeQuery(sql);
//判断resultSet集合中是否有下一个
while (resultSet.next()){
//输出数据库第一列的数据
System.out.println(resultSet.getObject(1));
System.out.println(resultSet.getObject(3));
System.out.println(resultSet.getObject(4));
复制代码

数据库student1表:

 输入正确的用户名密码

如果登录者在输入密码时恶意填入
1' OR '1'='1

 就算用户名不对,他也拿到了数据库中所有的数据

应对这样的情况就要使用预加载

预加载preparement

1.获取prepareStatement

//?表示占位符
String sql = " select * from where username = ? and password = ? "
//在创建的时候填写sql语句作为参数
PrepareStatement prepareStatement=connection.prepareStatement(sql)

2.设置占位符的值

//设置不同类型的参数,数字表示的是当前这个类型的第几个参数,推荐使用setObject
prepareStatement.setString(1, username);
prepareStatement.setString(2, password);

3.调用相应的增删改查方法,这时不需要再传入SQL语句,因为已经预加载了

ResultSet resultSet = prepareStatement.executeQuery();

将SQL语句预加载以后,我们在实验发现SQL注入没用了

总结:

当运行时动态地把参数传给PreprareStatement时, 即使参数里有敏感字符如 or’1=1’数据库也会把敏感字符作为一个参数,一个字段的属性值来处理而不会作为一个SQL指令, 如此,就起到了应对SQL注入的作用了!

 

posted @   时光里的少年  阅读(295)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示