复习_JDBC和sql注入问题

JDBC的全称为:java database connectivity (java和 数据库的连接 )
在这里插入图片描述
JDBC六步

  1. 注册驱动
  2. 建立数据库的连接
  3. 通过con连接获取到Statement实例
  4. statement执行sql语句,查询到的结果集到ResultSet实例
  5. 从结果集中获取数据
  6. 释放资源
package JDBC;

import com.mysql.jdbc.Driver;

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

public class JDBCTest {

    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Connection con = null;
        Statement statement = null;
        try {
            //获取连接
            con = getConnection();
            //创建statement
            statement = con.createStatement();
            // 执行添加语句
            String sql = "insert into user values('116','zhaoliu',28)";
            statement.executeUpdate(sql);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //释放资源
            release(con, statement, null);
        }
    }

    private static  String driverClass = "";
    private static String url = "";
    private static String username = "";
    private static String password = "";

    //解析properties文件只需要执行一次,所以放在静态代码块中
    static{
        //首先创建Properties对象
        Properties properties = new Properties();
        //加载文件
        try {
            properties.load(new FileInputStream("src/jdbc.properties"));
            //获取参数
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            Class.forName(driverClass);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static Connection getConnection(){
        Connection con = null;
        try {
            //2.获取连接
            con = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    //释放资源
    public static void release(Connection con,Statement st,ResultSet rs){
        //6.释放资源:先开后关,后开先关,最好放在finally代码块中
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


driverClass=com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybd
username = root
password = root

2.sql注入问题

sql注入:由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

案例:模拟登陆
执行如下sql语句:创建一个day06数据库,创建一张user表,表中插入一条数据。

create table user(
id varchar(10) primary key,
username varchar(10),
password varchar(10)
);
insert into user values('1','admin','123456');
package JDBC;

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

public class Login {
    public static void main(String[] args) {
        String username = "admin' -- ";
        String password = "123";
        Connection con = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            //首先获取连接
            con = JDBCUtil.getConnection();

            //创建statement对象
            statement = con.createStatement();
            //发送sql语句,查询数据库是否存在这个用户
            String sql = "select count(*) from user where username='" + username + "' and password = '" + password + "'";
            resultSet = statement.executeQuery(sql);

            int count = 0;
            while (resultSet.next()) {
                count = resultSet.getInt(1);
            }
            //如果不存在
            if (count == 0) {
                System.out.println("用户登录失败");
            } else {
                //存在
                System.out.println("用户登录成功");
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            JDBCUtil.release(con, statement, resultSet);
        }
    }
}

执行代码,可以发现用户名为 admin’ – ,密码为 1234 这样的用户是不存在的,但是尽然可以登录成功。那么这是什么原因造成的呢?
将字符串拼接后的sql语句放在可视化工具中查看发现如下情况:
在这里插入图片描述
可以发现,后面密码的验证被注释掉了。这样岂不是谁都可以登录了?

问题根本原因:
语句和用户输入的内容进行拼接,发送给数据库编译的时候,数据库将用户输入的内容当成sql语句编译了。
从而从根本上改变了我们开发者所期望sql语句原有的含义。导致程序受到sql攻击。那么原因知道了,我们怎么解决的?

问题的解决方案:
我们需要首先将sql语句所代表的含义确定下来,然后再向编译好的sql语句中填充用户输入的内容。这样用户输入的内容就不会再被编译了。所以需要我们学习preparedStatement向数据库发送预编译的sql语句。

2.1 PreparedStatement解决sql注入 重要步骤:

PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得
注意:sql提前创建好的。sql语句中需要参数。使用?进行占位。

  1. conn.prepareStatement(sql);
    需要你事先传递sql。如果sql需要参数,使用?进行占位。
  2. 设置参数(执行sql之前):prepStmt.setXXX(int index, 要放入的值)
    根据不同类型的数据进行方法的选择。第一个参数表示的是?出现的位置。从1开始计数,有几个问号,就需要传递接个参数。方法的参数说明:
    第一个参数:int index ;表示的是问号出现的位置。 问号是从1开始计数
    第二个参数:要问号的位置传入的值。
  3. 执行,不需要在传递sql了。
    prepStmt.executeQuery();—执行select
    prepStmt.executeUpdate();—执行insert,delete,update
package JDBC;

import java.sql.*;

public class Login {
    public static void main(String[] args) {
        String username = "admin";
        String password = "123456";
        Connection con = null;
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        try {
            //首先获取连接
            con = JDBCUtil.getConnection();

            String sql = "select COUNT(*) from user where username=? and password = ?";
            //创建preparedStatement对象,对sql进行编译
            prepareStatement = con.prepareStatement(sql);
            // 设置参数
            prepareStatement.setString(1, username);
            prepareStatement.setString(2, password);
            resultSet = prepareStatement.executeQuery();
            int count = 0;
            while (resultSet.next()) {
                count = resultSet.getInt(1);
            }
            //如果不存在
            if (count == 0) {
                System.out.println("用户登录失败");
            } else {
                //存在
                System.out.println("用户登录成功");
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            JDBCUtil.release(con, prepareStatement, resultSet);
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值