MySQL攻略 - JDBC程序SQL注入,PreparedStatement接口详解与案例练习,JDBC相关API小结

本文详细比较了Statement与PreparedStatement在Java JDBC中的使用,展示了SQL注入的风险以及PreparedStatement如何通过预处理语句有效防止攻击。实例涵盖了select, insert, update, delete和创建表操作,强调了预处理Statement的好处和最佳实践。
摘要由CSDN通过智能技术生成

SQL注入

请添加图片描述

Statement详解

基本介绍

statement是一个接口(interface statement)

  1. Statement对象,用于执行静态SQL语句并返回其生成的结果的对象
  2. 在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过
  • Statemetn【存在SQL注入问题】
  • PreparedStatement【预处理】
  • CallableStatement【存储过程】
  1. Statement对象执行SQL语句,存在SQL注入风险
  2. SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库
  3. 要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了

Navicat演示SQL注入

-- 演示sql 注入
-- 创建一张表
Create table admin (	-- 管理员表
Name varchar(32) not null unique,
pwd varchar(32) not null default ''
) character set utf8;

-- 添加数据
Insert into admin values('tom','123');

-- 查找某个管理是否存在

-- select * from admin where name = 'taotao' and pwd = '123';

-- SQL
-- 输入用户名 为 1 ' or
-- 输入密码 为 or '1' = '1
select * from admin where name = '1 ' or' and pwd = 'or '1' = '1';

JDBC演示SQL注入

package com.taotao.jdbc.statement;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 15:45
 */
@SuppressWarnings({"all"})
public class Statement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入管理员姓名:");
        String admin_name = sc.nextLine();  //nextline回车键代表此数据结束
        System.out.print("请输入管理员密码:");
        String admin_pwd = sc.nextLine();

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到statement,然后执行增删改查
        Statement statement = connection.createStatement();

        //4.组织SQL
        String sql = "select name,pwd from admin where name = '" + admin_name + "' and pwd = '"+ admin_pwd  +"'";

        ResultSet resultSet = statement.executeQuery(sql);
        if (resultSet.next()){  //如果查询到一条记录,则说明该管理存在
            System.out.println("恭喜,登陆成功");
        }else {
            System.out.println("登录失败");
        }

        //5.关闭连接资源
        resultSet.close();
        statement.close();
        connection.close();

    }
}

请添加图片描述

请添加图片描述

PreparedStatement详解

基本介绍

  1. PreparedStatement执行的SQL语句中的参数用问号(?)来表示,调用PreparedStatement对象的setXxx()方法来设置这些参数.setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
  2. 调用executeQuery(),返回ResultSet对象
  3. 调用executeUpdate(),执行更新,包括增、删、修改

预处理好处

  1. 不再使用 + 拼接sql语句,减少语法错误
  2. 有效的解决了sql注入问题!
  3. 大大减少了编译次数,效率较高

预处理案例(selete语句)

package com.taotao.jdbc.preparedstatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 16:54
 */
@SuppressWarnings({"all"})
public class PreparedStatement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入管理员姓名:");
        String admin_name = sc.nextLine();  //nextline回车键代表此数据结束
        System.out.print("请输入管理员密码:");
        String admin_pwd = sc.nextLine();

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到PreparedStatement
        //3.1.组织SQL,sql语句的 ? 就相当于占位符
        String sql = "select name,pwd from admin where name =?  and pwd =? ";
        //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //3.3给 ? 赋值
        preparedStatement.setString(1,admin_name);
        preparedStatement.setString(2,admin_pwd);

        //4.执行select 语句使用 executeQuery
        // 如果执行的是dml(update,insert,delete) executeUpdate()
        // 这里执行 executeQuery,不要再写 sql,因为已经被preparedStatement.setString语句处理过了
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()){  //如果查询到一条记录,则说明该管理存在
            System.out.println("恭喜,登陆成功");
        }else {
            System.out.println("登录失败");
        }

        //5.关闭连接资源
        resultSet.close();
        preparedStatement.close();
        connection.close();

    }
}

预处理案例(insert语句)

package com.taotao.jdbc.preparedstatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 16:54
 */
@SuppressWarnings({"all"})
public class PreparedStatement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入添加用户姓名");
        String admin_name = sc.nextLine();  //nextline回车键代表此数据结束
        System.out.print("请输入添加用户密码");
        String admin_pwd = sc.nextLine();

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到PreparedStatement
        //3.1.组织SQL,sql语句的 ? 就相当于占位符
        String sql = "insert into admin values(?,?) ";
        //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //3.3给 ? 赋值
        preparedStatement.setString(1,admin_name);
        preparedStatement.setString(2,admin_pwd);

        //4.执行select 语句使用 executeQuery
        // 如果执行的是dml(update,insert,delete) executeUpdate()
        // 这里执行 executeQuery,不要再写 sql,因为已经被preparedStatement.setString语句处理过了
        int i = preparedStatement.executeUpdate();

        System.out.println("创建用户" + (i == 1 ? "成功":"失败" ));

        //5.关闭连接资源
        preparedStatement.close();
        connection.close();

    }
}

预处理案例(update语句)

package com.taotao.jdbc.preparedstatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 16:54
 */
@SuppressWarnings({"all"})
public class PreparedStatement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入管理员姓名");
        String admin_name = sc.nextLine();  //nextline回车键代表此数据结束
        System.out.print("请输入新的密码");
        String admin_pwd = sc.nextLine();

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到PreparedStatement
        //3.1.组织SQL,sql语句的 ? 就相当于占位符
        String sql = "update admin set pwd = ? where name = ?";
        //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //3.3给 ? 赋值
        preparedStatement.setString(2,admin_name);
        preparedStatement.setString(1,admin_pwd);

        //4.执行select 语句使用 executeQuery
        // 如果执行的是dml(update,insert,delete) executeUpdate()
        // 这里执行 executeQuery,不要再写 sql,因为已经被preparedStatement.setString语句处理过了
        int i = preparedStatement.executeUpdate();

        System.out.println("修改用户密码" + (i == 1 ? "成功":"失败" ));

        //5.关闭连接资源
        preparedStatement.close();
        connection.close();
    }
}

预处理案例(delete语句)

package com.taotao.jdbc.preparedstatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 16:54
 */
@SuppressWarnings({"all"})
public class PreparedStatement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入要删除的管理员姓名");
        String admin_name = sc.nextLine();  //nextline回车键代表此数据结束

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到PreparedStatement
        //3.1.组织SQL,sql语句的 ? 就相当于占位符
        String sql = "delete from admin where name = ?";
        //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //3.3给 ? 赋值
        preparedStatement.setString(1,admin_name);

        //4.执行select 语句使用 executeQuery
        // 如果执行的是dml(update,insert,delete) executeUpdate()
        // 这里执行 executeQuery,不要再写 sql,因为已经被preparedStatement.setString语句处理过了
        int i = preparedStatement.executeUpdate();

        System.out.println("删除用户成功" + (i == 1 ? "成功":"失败" ));

        //5.关闭连接资源
        preparedStatement.close();
        connection.close();
    }
}

预处理案例(create表)

package com.taotao.jdbc.preparedstatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * Create By 刘鸿涛
 * 2022/3/1 16:54
 */
@SuppressWarnings({"all"})
public class PreparedStatement_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);

        //让用户输入管理员和密码
        System.out.print("请输入要创建的表名称");
        String table_Name = sc.nextLine();  //nextline回车键代表此数据结束

        //通过Properties对象获取配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));

        //获取账号密码
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        //获取驱动
        String url = properties.getProperty("url");

        //1.加载Driver类
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接SQL
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到PreparedStatement
        //3.1.组织SQL,sql语句的 ? 就相当于占位符
        String sql = "create table "+table_Name+"(id int)";
        //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //4.创建表要用execute,并且返回的布尔值
        boolean execute = preparedStatement.execute(sql);

        System.out.println("创建表" + (execute == false ? "成功":"失败" ));

        //5.关闭连接资源
        preparedStatement.close();
        connection.close();
    }
}

注意

  • 占位符不能用于表名和列名!

JDBC的相关API小结

DriverManager驱动管理类

getConnection(url,user,pwd):获取连接

Connection接口

createStatement():生成命令对象

prepareStatement(sql):生成预编译命令对象

请添加图片描述

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼鬼骑士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值