• Java学习笔记47(JDBC、SQL注入攻击原理以及解决)


    JDBC:java的数据库连接

    JDBC本质是一套API,由开发公司定义的类和接口

    这里使用mysql驱动,是一套类库,实现了接口

    驱动程序类库,实现接口重写方法,由驱动程序操作数据库

    JDBC操作步骤:

    1.注册驱动

    2.获得连接

    3.获得语句执行平台

    4.执行sql语句

    5.处理结果

    6.释放资源

    1.导入jar包,可以在网上下载到,这里使用的是:mysql-connector-java-5.1.37-bin.jar

    注册驱动:

    package demo;
    
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    import com.mysql.jdbc.Driver;
    
    public class JDBCDemo {
        public static void main(String[] args) throws SQLException, ClassNotFoundException {
            //注册驱动
            //DriverManager.registerDriver(new Driver());
            //不推荐上边这种方法,建议用反射技术,将驱动类加入内存
            Class.forName("com.mysql.jdbc.Driver");
        }
    }

    2.获得连接:

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class JDBCDemo {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            Class.forName("com.mysql.jdbc.Driver");
            //获得数据库连接
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url,username,password);
            System.out.println(con);
        }
    }

    3.获取语句执行平台

    通过数据库连接对象,获取到sql语句的执行者对象

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class JDBCDemo {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url,username,password);
            //获取语句执行平台
            Statement stat = con.createStatement();
            System.out.println(stat);
        }
    }

    4.执行sql语句:

    准备数据:

    CREATE TABLE sort(
        sid INT PRIMARY KEY AUTO_INCREMENT,
        sname VARCHAR(100),
        sprice DOUBLE,
        sdesc VARCHAR(5000)
        );
    INSERT INTO sort(sname,sprice,sdesc) VALUES('家电',2000,'促销'),
    ('家具',8900,'价格上涨'),
    ('玩具',300,'赚钱'),
    ('生鲜',500.99,'促销'),
    ('服装',24000,'促销'),
    ('洗涤',50,'促销');
    
    SELECT * FROM sort;

    执行sql语句:

    1.增删改

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class JDBCDemo {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url,username,password);
            Statement stat = con.createStatement();
            //执行sql语句
            //这种方法注意:只能使用insert,delete,update语句
            int row = stat.executeUpdate("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽车',2000,'促销');");
            System.out.println(row);
            //释放资源
            stat.close();
            con.close();
        }
    }

    2.查询

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class JDBCDemo {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url,username,password);
            Statement stat = con.createStatement();
            //查询sql语句
            String sql= "SELECT * FROM sort"; 
            //这个方法用于执行sql中的select查询
            ResultSet rs = stat.executeQuery(sql);
            //处理结果集
            while(rs.next()){
                //获取每列数据
                System.out.println(rs.getInt("sid")+"   "+rs.getString("sname")+
                        "   "+rs.getDouble("sprice")+"   "+rs.getString("sdesc"));
            }
            rs.close();
            stat.close();
            con.close();
        }
    }

    输出:



    SQL注入攻击简单案例:

    CREATE TABLE users(
         id INT PRIMARY KEY AUTO_INCREMENT,
         username VARCHAR(100),
         PASSWORD VARCHAR(100)
    );
    
    INSERT INTO users (username,PASSWORD) VALUES ('a','1'),('b','2');
    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    /*
     *  Java程序实现用户登录,用户名和密码,数据库检查
     *  演示被别人注入攻击
     */
    public class JDBCDemo {
        public static void main(String[] args)throws Exception {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url, username, password);
            Statement stat = con.createStatement();
            
            Scanner sc = new Scanner(System.in);
            String user = sc.nextLine();
            String pass = sc.nextLine();
            
            //执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
            String sql = "SELECT * FROM users WHERE username='"+user+"' AND PASSWORD='"+pass+"'";
            System.out.println(sql);
            ResultSet rs = stat.executeQuery(sql);
            while(rs.next()){
                System.out.println(rs.getString("username")+"   "+rs.getString("password"));
            }
            
            rs.close();
            stat.close();
            con.close();
        }
    }

    正常情况,必须输入a,1或者b,2才可以登录成功

    这里如果这样输入:

    1=1恒成立,or两边只要有一边成立就会成功,这里就实现了最简单的sql注入攻击

    解决:


    使用PrepareStatement接口

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    /*
     *  Java程序实现用户登录,用户名和密码,数据库检查
     *  防止注入攻击
     *  Statement接口实现类,作用执行SQL语句,返回结果集
     *  有一个子接口PreparedStatement  (SQL预编译存储,多次高效的执行SQL) 
     *  PreparedStatement的实现类数据库的驱动中,如何获取接口的实现类
     *  
     *  是Connection数据库连接对象的方法
     *  PreparedStatement prepareStatement(String sql) 
              
     */
    public class JDBCDemo {
        public static void main(String[] args)throws Exception {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username = "root";
            String password = "xuyiqing";
            Connection con = DriverManager.getConnection(url, username, password);
            Scanner sc = new Scanner(System.in);
            String user = sc.nextLine();
            String pass = sc.nextLine();
            
            //执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
            String sql = "SELECT * FROM users WHERE username=? AND PASSWORD=?";
            //调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类
            //方法中参数,SQL语句中的参数全部采用问号占位符
            PreparedStatement pst =  con.prepareStatement(sql);
            System.out.println(pst);
            //调用pst对象set方法,设置问号占位符上的参数
            pst.setObject(1, user);
            pst.setObject(2, pass);
            
            //调用方法,执行SQL,获取结果集
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("username")+"   "+rs.getString("password"));
            }
            
            rs.close();
            pst.close();
            con.close();
        }
    }

    发现这个接口更安全,所以建议使用这个接口实现增删改查

    使用PrepareStatement接口,实现数据表的更新操作

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    
    /*
     *  使用PrepareStatement接口,实现数据表的更新操作
     */
    public class JDBCDemo {
        public static void main(String[] args) throws Exception{
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username="root";
            String password="xuyiqing";
            Connection con = DriverManager.getConnection(url, username, password);    
            
            //拼写修改的SQL语句,参数采用?占位
            String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?";
            //调用数据库连接对象con的方法prepareStatement获取SQL语句的预编译对象
            PreparedStatement pst = con.prepareStatement(sql);
            //调用pst的方法setXXX设置?占位
            pst.setObject(1, "车");
            pst.setObject(2, 49988);
            pst.setObject(3, 7);
            //调用pst方法执行SQL语句
            pst.executeUpdate();
            
            pst.close();
            con.close();
        }
    }

     PrepareStatement接口实现数据表的查询操作

    package demo;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    /*
     *  PrepareStatement接口实现数据表的查询操作
     */
    public class JDBCDemo {
        public static void main(String[] args) throws Exception{
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybase";
            String username="root";
            String password="xuyiqing";
            Connection con = DriverManager.getConnection(url, username, password);    
            
            String sql = "SELECT * FROM sort";
            
            PreparedStatement pst = con.prepareStatement(sql);
            
            //调用pst对象的方法,执行查询语句,Select
            ResultSet rs=pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("sid")+"  "+rs.getString("sname")+"  "+rs.getString("sprice")+"  "+rs.getString("sdesc"));
            }
            rs.close();
            pst.close();
            con.close();
        }
    }
  • 相关阅读:
    你的DNN站点慢了么?
    SQL锁的应用与描述之二
    自动完成输入框错位
    网页插入flash代码以及技巧
    使用T_SQL脚本创建SQLServer2000后台计划作业任务
    SQL Server实用经典例句之二
    中缀表达式转后缀表达式
    spring cloud config server SSH配置 git private key方式
    vim 技巧一
    jquery 监控文本框键盘事件(回车事件),附常用keycode值。
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/8323664.html
Copyright © 2020-2023  润新知