jdbc_mysql(二)Statement实现sql注入,PrepareStatement解决注入

一、 问题描述

目标:java通过键盘输入关键词拼接成sql去数据库中查找。
存在问题:键盘输入关键字,拼接后没有产生过滤效果,反而查出了所有记录

二、Statement代码实现

1.在src目录下新建injection.properties连接数据库的配置文件

url=jdbc:mysql://192.168.132.2:3306/mysql_test
user=mysql_test
password=BJjbHSKFGESJrtpP

2.新建连接数据库的工具类InjectionUtils,实现连接数据库、释放资源的通用功能

package util;

import com.sun.glass.ui.EventLoop;
import sun.java2d.pipe.DrawImage;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class InjectionUtils {
    /**
     * 1.定义静态变量,存放配置文件中值
     * 2.定义静态代码块,获取配置文件值
     * 3.获取数据库连接
     * 4.释放资源
     */
    //1.定义静态变量,存放配置文件中值
    private static String url;
    private static String username;
    private static String password;
    //2.定义静态代码块,获取配置文件值
    static{
        //1.使用ClassLoader获取src下配置配件injection.properties的相对路径
        ClassLoader classLoader = InjectionUtils.class.getClassLoader();
        URL resource = classLoader.getResource("injection.properties");
        String path = resource.getPath();
        //2.使用Properties类获取配置文件值
        Properties pro = new Properties();
        //3.给pro绑定数据
        try {
            pro.load(new FileReader(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //4.获取数据
        url = pro.getProperty("url");
        username = pro.getProperty("user");
        password = pro.getProperty("password");
    }
    //3.获取数据库连接,返回连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    // 4.释放资源,重载方法
    public static void close(ResultSet rs, Statement stat, Connection conn){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stat != null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(Statement stat, Connection conn){
        if(stat != null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2.新建实现类SqlInjection,实现键盘输入参数,返回查询结果

package jdbc;

import util.InjectionUtils;

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

public class SqlInjection {
/**
 * 目的:通过键盘输入两个参数,查询数据库结果
 * 1.定义一个查询方法,接受键盘输入值,拼接sql语句,返回查询结果。
 * 2.main方法中键盘输入两个值,显示查询结果
 */
    public static void main(String[] args) {
        //1.键盘输入,接收用户名、密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        //2.展示查询结果
        new SqlInjection().query(username,password);
    }
    public void query(String username, String password){

        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //1.连接数据库
            conn = InjectionUtils.getConnection();
            //2.定义sql
            String sql = "select * from user where username ='"+username+"' and password ='"+password+"'";
            //3.获取执行sql对象
            stat = conn.createStatement();
            //4.执行sql,存储返回结果
            rs = stat.executeQuery(sql);
            //5.输出查询结果
            while(rs.next()){
                String un = rs.getString(2);
                String pd = rs.getString(3);
                System.out.println(un+" : "+pd);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            InjectionUtils.close(rs,stat,conn);
        }
    }
}

三、注入原理解释

使用sql拼接,所有下图2中拼接成的sql中where条件是true,所以显示全部数据。导致过滤条件无效
jdbc_mysql(二)Statement实现sql注入,PrepareStatement解决注入_第1张图片

四、使用PrepareStatement解决注入

新建方法,使用PrepareStatement执行sql,调用这个方法,不会产生注入

  public void queryPrepareStatement(String username, String password){

        Connection conn = null;
        PreparedStatement ppst = null;
        ResultSet rs = null;
        try {
            //1.连接数据库
            conn = InjectionUtils.getConnection();
            //2.定义sql,?表示占位符,并给占位符赋值
            String sql = "select * from user where username = ?  and password = ?";
            //3.获取执行sql对象,给占位符赋值
            ppst = conn.prepareStatement(sql);
            ppst.setString(1,username);
            ppst.setString(2,password);
            //4.执行sql,存储返回结果
            rs = ppst.executeQuery();
//            System.out.println(sql);
            //5.输出查询结果
            while(rs.next()){
                String un = rs.getString(2);
                String pd = rs.getString(3);
                System.out.println(un+" : "+pd);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            InjectionUtils.close(rs,ppst,conn);
        }
    }

你可能感兴趣的:(java,mysql)