MySql教程

MySQL学习记录11JDBCstatement对象、SQL注入问题与PreparedStatement对象

本文主要是介绍MySQL学习记录11JDBCstatement对象、SQL注入问题与PreparedStatement对象,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • MySQL学习记录11JDBCstatement对象、SQL注入问题与PreparedStatement对象
    • 11.1statement对象
      • 11.1.1代码实现(增删改查)
      • 11.1.2SQL注入问题
        • 11.1.2.1SQL注入攻击的总体思路
    • 11.2PreparedStatement对象

MySQL学习记录11JDBCstatement对象、SQL注入问题与PreparedStatement对象

11.1statement对象

Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即受影响的行数)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。

CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

        Statement statement = connection.createStatement();
        String sql = "insert into user(... ) values(... . ) ";
        int num = statement.executeUpdate(sql);
        if (num > 0) {
            System.out.println("插入成功!!! ");
        }

CRUD操作-delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:

        Statement statement = connection.createStatement();
        String sql = "delete from user where id = 1";
        int num = statement.executeUpdate(sql);
        if (num > 0) {
            System.out.println("删除成功!!! ");
        }

CRUD操作-update
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:

        Statement statement = connection.createStatement();
        String sql = "update user set name = '' where name = '' ";
        int num = statement.executeUpdate(sql);
        if (num > 0) {
            System.out.println("修改成功!!! ");
        }

CRUD操作-read
使用executeUpdate(String sql)方法完成数据查询操作,示例操作:

        Statement statement = connection.createStatement();
        String sql = "select * from user where id = 1";
        ResultSet resultSet = statement.executeUpdate(sql);
        where(resultSet .next()){
        //根据获取列的数据类型,分别调用resultSet的相应方法映射到java对象中
        }

11.1.1代码实现(增删改查)

首先编写数据库配置文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123456

其次编写jdbc工具类:

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {

    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    static {
        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);

            //从db.properties中读取这四个信息
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //1.驱动只用加载一次
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //释放连接
    public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {
        if (rs != null) {
            rs.close();
        }
        if (st != null) {
            st.close();
        }
        if (conn != null) {
            conn.close();
        }
    }
}

插入测试:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestInsert {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了
            st = conn.createStatement();  //获得SQL的执行对象
            String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" +
                    "VALUES(4,'zhaoliu','123456','XXXX@qq.com','2020-01-01')";
            int i = st.executeUpdate(sql);  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("插入成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
查看数据库表中的结果:
在这里插入图片描述
插入成功!
既然插入的代码成功了,那么删除:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestDelete {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了
            st = conn.createStatement();  //获得SQL的执行对象
            String sql = "DELETE FROM users WHERE id = 4";
            int i = st.executeUpdate(sql);  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("删除成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

可以观察到,与插入测试代码不同的只有sql语句,最多再改改操作成功的提示,其他都无需变动。

运行代码:
在这里插入图片描述
查看数据库表数据:
在这里插入图片描述
删除成功!
再来一段更新:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了
            st = conn.createStatement();  //获得SQL的执行对象
            String sql = "UPDATE users SET `NAME`='madongmei',`email`='XXXXXX@qq.com' WHERE id = 1;";
            int i = st.executeUpdate(sql);  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("更新成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
在这里插入图片描述
更新成功!

查询:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSelect {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了
            st = conn.createStatement();  //获得SQL的执行对象

            String sql = "select * from users where id = 1";

            rs = st.executeQuery(sql);  //查询完毕会返回一个结果集
            while (rs.next()) {
                System.out.println(rs.getString("NAME"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述

11.1.2SQL注入问题

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。

11.1.2.1SQL注入攻击的总体思路

  • 寻找到SQL注入的位置
  • 判断服务器类型和后台数据库类型
  • 针对不同的服务器和数据库特点进行SQL注入攻击

案例:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SqlInjection {
    public static void main(String[] args) {
        login("madongei", "123456");

    }

    public static void login(String username, String password) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了
            st = conn.createStatement();  //获得SQL的执行对象

            String sql = "select * from users where `NAME`='" + username + "' AND `PASSWORD` = '" + password + "'";

            rs = st.executeQuery(sql);  //查询完毕会返回一个结果集
            while (rs.next()) {
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("PASSWORD"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn, st, rs);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

如果能正常登录,则应输出用户名、密码的结果
但:
在这里插入图片描述
如果将上述代码中login("madongei", "123456");改为login("'or '1=1","123456");
在这里插入图片描述
所有的用户名和密码都被盗取。

11.2PreparedStatement对象

防止sql注入且效率更高
1、新增

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.*;
import java.util.Date;

public class TestInsert {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            //区别 使用?占位符代替参数
            String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" + "VALUES(?,?,?,?,?)";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行

            //手动给参数赋值
            st.setInt(1, 4);
            st.setString(2, "haha");
            st.setString(3, "123456");
            st.setString(4, "ssss@qq.com");
            //注意点 sql.Date
            //      util.Date
            st.setDate(5, new java.sql.Date(new Date().getTime()));

            //执行
            int i = st.executeUpdate();  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("插入成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
在这里插入图片描述
2、删除

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

public class TestDelete {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            //区别 使用?占位符代替参数
            String sql = "delete from users where id = ?";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行

            //手动给参数赋值
            st.setInt(1,4);

            //执行
            int i = st.executeUpdate();  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("删除成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
在这里插入图片描述
3、更新

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            //区别 使用?占位符代替参数
            String sql = "update users set `NAME` = ? where id = ?;";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行

            //手动给参数赋值
            st.setString(1, "xialuo");
            st.setInt(2, 1);

            //执行
            int i = st.executeUpdate();  //把sql语句丢进去执行,i是受影响的行数
            if (i > 0) {
                System.out.println("更新成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
在这里插入图片描述
4、查询

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.*;

public class TestSelect {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            //区别 使用?占位符代替参数
            String sql = "select * from users where id = ?";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行

            //手动给参数赋值
            st.setInt(1, 1);

            //执行
            rs = st.executeQuery();  //把sql语句丢进去执行,i是受影响的行数
            if (rs.next()) {
                System.out.println(rs.getString("NAME"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

在这里插入图片描述
5、防止sql注入
正常业务:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.*;

public class SqlInjection {
    public static void main(String[] args) {
        login("xialuo", "123456");

        //login("'or '1=1","123456");
    }

    public static void login(String username, String password) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            String sql = "select * from users where `NAME`=? AND `PASSWORD`=?";

            st = conn.prepareStatement(sql);  //预编译sql
            st.setString(1,username);
            st.setString(2,password);


            rs = st.executeQuery();  //查询完毕会返回一个结果集
            while (rs.next()) {
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("PASSWORD"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn, st, rs);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
拼接sql:

import com.jatine.lesson02.utils.JdbcUtils;

import java.sql.*;

public class SqlInjection {
    public static void main(String[] args) {
        //login("xialuo", "123456");

        login("''or 1=1","123456");
    }

    public static void login(String username, String password) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();  //获取数据库连接,这样就连接上了,不用再写那些配置了

            String sql = "select * from users where `NAME`=? AND `PASSWORD`=?";

            st = conn.prepareStatement(sql);  //预编译sql
            st.setString(1,username);
            st.setString(2,password);


            rs = st.executeQuery();  //查询完毕会返回一个结果集
            while (rs.next()) {
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("PASSWORD"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn, st, rs);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
没有结果,也没有报错

这篇关于MySQL学习记录11JDBCstatement对象、SQL注入问题与PreparedStatement对象的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!