美文网首页程序员
009-JDBC,防SQL注入

009-JDBC,防SQL注入

作者: Ktry | 来源:发表于2020-03-16 09:09 被阅读0次

    DBC

    Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
    

    JDBC的开发步骤

    /**
     * 0、准备工作:导入jar包
     *         a、在工程下新建一个lib文件夹
     *     b、将数据库驱动包,放入到文件夹中,并添加到classpath中
     *              右击jar包,build path ---- >  add to build path     
     * 1、注册驱动
     *             a、DriverManager类的resgister方法来注册驱动
     *             b、利用反射技术来注册驱动
     *  Class.forName("com.mysql.jdbc.Driver");
     *     2、获取数据库连接对象
     *  Connection conn  = DriverManager.getConnection(url,username,password); 
     * 
     * 3、获取数据库操作对象
     * Statement stat = conn.createStatement();
     * 
     * 4、执行sql语句,获取结果集    
     * String sql = "xxxxx";
     * int count = stat.executeUpdate(sql);
     * 
     * 5、处理结果集
     * System.out.println(count);
     * 
     * 6、关闭资源
     * stat.close();
     * conn.close();
     * 
     */
    

    JDBC代码实现

    public class JDBCDemo1 {
        public static void main(String[] args) throws SQLException, ClassNotFoundException {
            //1、注册驱动
    //        Driver driver = new Driver();
    //        DriverManager.registerDriver(driver);
            //全限定名  包名+类名   执行这句话,相当于类被加载了,通过原码发现,这个Driver类被加载,他的静态代码块就会被执行,驱动就注册上了
            Class.forName("com.mysql.jdbc.Driver");
    
            //2、获取数据库连接对象Connection对象
            /*
             *     url  连接数据库的地址  
             * 网络通信三要素     ip地址  协议    端口
             *  http://www.baidu.com:80
             *  本机的回路地址 :localhost    127.0.0.1   192.168.71.40
             *  
             *  jdbc:mysql://localhost:3306/数据库名
             *  如果是连接的本机的数据库可以简写为:
             *  jdbc:mysql:///数据库名
             * 
             *     在5.7的版本中,运行程序会有警告,SSL协议不可用
             * jdbc:mysql:///数据库名?useSSL=false
             * 
             * 
             *     user   数据库用户名
             *  password  数据库密码
             * 
             * */
            String url = "jdbc:mysql:///java?useSSL=false";
            String user = "root";
            String password = "root";
            Connection conn = DriverManager.getConnection(url, user, password);
    
            //System.out.println(conn);
    
            //3、获取Statement对象操作数据库
            Statement stat = conn.createStatement();
    
            //4、执行sql语句并,返回结果集
            /* 
             *  针对的增删改    
             *     stat.executeUpdate(sql)    返回值是受影响行数
             *  针对的是查询
             *     stat.executeQuery(sql)      结果集
             * */
            String sql = "insert into student values(1,'zhangsan','1班')";
            int count = stat.executeUpdate(sql);
            //5、处理结果
            System.out.println("受影响的行数为"+count);
            //6、关闭资源
            stat.close();
            conn.close();
    
        }
    }
    

    JDBC实现查询

    public class JDBCDemo2 {
        public static void main(String[] args) {
            ResultSet rs = null;
            Statement stat = null;
            Connection conn = null;
            try {
                //1、注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2、获取数据库连接对象Connection
                String url = "jdbc:mysql:///java?useSSL=false";
                String user = "root";
                String password = "root";
                conn = DriverManager.getConnection(url, user, password);
                //3、获取数据操作对象
                stat = conn.createStatement();
                //4、通过Statement对象执行SQL语句,返回ResultSet结果集
                String sql = "select * from student";
                rs = stat.executeQuery(sql);
                /**
                 * rs.next(); 判断是否有下一个,如果有将游标往下移动一位,返回true。,如果没有返回false
                 * 
                 * rs.getXXX 方法  用与从结果集中获取数据。
                 *  XXX 取决于数据在数据库中的类型
                 *  int    ------ > getInt("字段名");
                 *  double ----> getDouble("字段名");
                 *  varchar ---->getString("字段名");
                 *  date ------>getDate("字段名");
                 *  
                 */
    //            rs.next();
    //            int sid = rs.getInt("sid");
    //            String sname = rs.getString("sname");
    //            String scalss = rs.getString("sclass");
    //            System.out.println(sid);
    //            System.out.println(sname);
    //            System.out.println(scalss);
                //5、处理结果集
                while(rs.next()) {
                    int sid = rs.getInt("sid");
                    String sname = rs.getString("sname");
                    String sclass = rs.getString("sclass");
                    System.out.println(sid);
                    System.out.println(sname);
                    System.out.println(sclass);
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //6、关闭资源
                /**
                 *  rs 对象、  stat 对象、conn 对象
                 */
                try {
                    if(rs != null) {
                        rs.close();
                    }
                    if(stat != null) {
                        stat.close();
                    }
                    if(conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }        
        }
    }
    

    ORM思想

    对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。
    

    ORM代码实现

    public class JDBCDemo3 {
        public static void main(String[] args) {
            Connection conn = null;
            Statement stat = null;
            ResultSet rs = null;
            //1、注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //2、获取数据库连接对象 Connection
                conn = DriverManager.getConnection("jdbc:mysql:///java", "root", "root");
                //3、获取Statement对象 
                stat = conn.createStatement();
                //4、执行sql语句获取结果集
                rs = stat.executeQuery("select * from student");
    
                //定义一个List集合用于存放结果集中的数据
                List<Student> list = new ArrayList<Student>();
                //5、处理结果集
                while(rs.next()) {
                    Student stu = new Student();
    
                    //从结果集中一行获取数据
                    int sid = rs.getInt("sid");
                    String sname = rs.getString("sname");
                    String sclass = rs.getString("sclass");
    
                    //将结果添加到对象中
                    stu.setSid(sid);
                    stu.setSname(sname);
                    stu.setSclass(sclass);
    
                    //将对象添加到List集合中
                    list.add(stu);
                }
                System.out.println(list);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //关闭资源
                try {
                    if(conn != null) {
                        conn.close();
                    }
                    if(stat != null) {
                        stat.close();
                    }
                    if(rs != null) {
                        rs.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    ORM的核心代码

    //定义一个List集合用于存放结果集中的数据
    List<Student> list = new ArrayList<Student>();
    //5、处理结果集
    while(rs.next()) {
        Student stu = new Student();
    
        //从结果集中一行获取数据
        int sid = rs.getInt("sid");
        String sname = rs.getString("sname");
        String sclass = rs.getString("sclass");
    
        //将结果添加到对象中
        stu.setSid(sid);
        stu.setSname(sname);
        stu.setSclass(sclass);
    
        //将对象添加到List集合中
        list.add(stu);
    }
    

    抽取工具类

    因为每次获取数据库的连接对象比较麻烦,且加载驱动的操作只需执行一次,所以封装一个工具类专门用于获取Connection连接对象
    

    工具类实现

    /**
     * JDBC工具类
     *   1、获取数据库连接对象 Connection
     *   2、关闭资源
     */
    public class JDBCUtils {
        private static final String DRIVER = "com.mysql.jdbc.Driver";
        private static final String URL = "jdbc:mysql:///java?useSSL=false";
        private static final String USERNAME = "root";
        private static final String PASSWORD = "root";
        static {
            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        //获取Connection对象
        public static Connection getConnetion() {
            Connection conn = null;
            try {
                 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return conn;
        }
        //关闭资源
        public static void close(Connection conn , Statement stat,ResultSet rs) {
                try {
                    if(conn != null) {
                        conn.close();
                    }
                    if(rs != null) {
                        rs.close();
                    }
                    if(stat != null) {
                        stat.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }
    
    

    使用工具类

    public class JDBCDemo1 {
        public static void main(String[] args) {
            Connection conn  = null;
            Statement stat = null;
            ResultSet rs = null;
            try {
                //2、获取Connection对象
                conn  = JDBCUtils.getConnetion();
                //3、获取Statement对象
                stat = conn.createStatement();
                //4、执行sql语句返回结果集
                rs = stat.executeQuery("select * from student where sid = 1");
                //5、处理结果集
                Student student = null;
                while(rs.next()) {
                    student = new Student();
                    student.setSid(rs.getInt("sid"));
                    student.setSname(rs.getString("sname"));
                    student.setSclass(rs.getString("sclass"));
                }
                System.out.println(student);
    
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //6、关闭资源
                JDBCUtils.close(conn, stat, rs);
            }
        }
    }
    
    

    JDBC实现登录

    public class LoginDemo {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名");
            String username = sc.nextLine();
            System.out.println("请输入密码");
            String password = sc.nextLine();
            Connection conn  = null;
            Statement stat = null;
            ResultSet rs = null;
            try {
                //2、获取Connection对象
                conn  = JDBCUtils.getConnetion();
                //3、获取Statement对象
                stat = conn.createStatement();
                //4、执行sql语句返回结果集
                //select * from tb_user where username = 'cxk' and password = '250' or 1 = 1;
                // xxxx' or 1 = '1
                String sql = "select * from tb_user where username = '" +username + "' and password = '" + password +"'";
                System.out.println(sql);
                rs = stat.executeQuery(sql);
                //5、处理结果集
                User user = null;
                while(rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));
                }
                if(user != null) {
                    System.out.println("登录成功");
                }else {
                    System.out.println("登录失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //6、关闭资源
                JDBCUtils.close(conn, stat, rs);
            }
        }
    }
    
    

    登录的问题

    在使用Statement对象的时候的问题:
    1、在拼接字符串的时候需要自己手动的加上引号
    2、可能会出现SQL注入的问题
    当 密码输入  xxxxx' or 1 = '1   那么这时,任意的密码都会被当做登录成功
    
    

    PreparedStatement使用

    public class LoginDemo2 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名");
            String username = sc.nextLine();
            System.out.println("请输入密码");
            String password = sc.nextLine();
            Connection conn  = null;
            Statement stat = null;
            ResultSet rs = null;
            try {
                //2、获取Connection对象
                conn  = JDBCUtils.getConnetion();
                //3、获取PreparedStatement对象   预加载sql语句
                String sql = "select * from tb_user where username = ? and password = ?";
                PreparedStatement ps  = conn.prepareStatement(sql);
                //将占位符替换成指定的值   ? 表示占位符    下标从左往右 1 开始
                ps.setString(1, username);
                ps.setString(2, password);
    
                System.out.println(ps);
                //4、执行sql语句获取结果集
                rs = ps.executeQuery();
    
                //5、处理结果集
                User user = null;
                while(rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));
                }
                if(user != null) {
                    System.out.println("登录成功");
                }else {
                    System.out.println("登录失败");
                }            
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //6、关闭资源
                JDBCUtils.close(conn, stat, rs);
            }
        }
    }
    
    

    Statement和PreparedStatement区别

    1、PreparedStatement是Statement的子接口
    2、PreparedStatement可以实现预加载,在编写SQL语句的时候可以使用?号作为占位符且在传递参数的时候会自动加上引号。
    3、PreparedStatement能防止SQL注入
    
    所谓的预加载就是传入SQL语句的时机,Statement是在执行SQL语句的是传递SQL。PreparedStatement是在创建对象的时候就传递SQL,所以就称之为预加载,利用这个在写SQL语句的时候可以用?号作为占位符,然后再传递参数
    
    

    相关文章

      网友评论

        本文标题:009-JDBC,防SQL注入

        本文链接:https://www.haomeiwen.com/subject/apewehtx.html