• 学习记录07 --- 升级DBTools,防止SQL注入


    今天上午才了解到我之前写的DBTools会导致sql注入,所以今天来升级下这个DBTools

    这次我们连接数据库就不用一个方法了,直接在static里面完成

     1 //创建一个静态代码块连接数据库
     2     static {
     3         try {
     4             //导入驱动类
     5             Class.forName("com.mysql.jdbc.Driver");
     6             //创建连接对象
     7             conn = DriverManager.getConnection(url,user,pwd);
     8         } catch (ClassNotFoundException | SQLException e) {
     9             e.printStackTrace();
    10         }
    11     }

    这样在程序执行的时候就连接了数据库,不需要再调用一个方法了

    那么先来重写查询的方法,我们原本的方法是这样的

     1 //数据库查询操作
     2     public static ResultSet executeQuery(String sql) throws Exception {
     3         //调用连接数据库方法连接数据库
     4         connetcDatabase();
     5         //创建命令行
     6         stt = conn.createStatement();
     7         //执行sql语句
     8         ResultSet result = stt.executeQuery(sql);
     9         //返回操作结果
    10         return result;
    11     }

    如果按照以上方式写,使用Statement对象,很容易导致SQL注入,我们就可以这样写

    1 //数据库查询操作
    2     public static ResultSet executeQuery(String sql) throws Exception {
    3         //创建命令行
    4         PreparedStatement ppt = conn.prepareStatement(sql);
    5         //执行sql语句
    6         ResultSet result = ppt.executeQuery();
    7         //返回操作结果
    8         return result;
    9     }

    那使用预编译的Statement可以防止sql注入,因为这个是把值当作参数传给sql语句

    也就是说我们需要传值的地方写个?   然后使用setObject等等方式来进行传值

    但是这里有个问题,我们不知道会有多少个参数,那就需要可变参数来完成,然后用for循环遍历

     1 //数据库查询操作
     2     public static ResultSet executeQuery(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //执行sql语句
    10         ResultSet result = ppt.executeQuery();
    11         //返回操作结果
    12         return result;
    13     }

    但是这还有个问题,因为查询全部的话,就不需要传参数过来,那么objs为null就会报异常

    那么我们需要在for的条件判断再加一个

    //遍历传值
            for(int i=0;objs!=null&&i<objs.length;i++){
                ppt.setObject(i+1,objs[i]);
            }

    那么这样就解决了这个问题,那么增删改的也是一样,复制过去

     1 //数据库增删改操作
     2     public static int executeUpdate(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;objs!=null&&i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //执行sql语句
    10         int line = ppt.executeUpdate();
    11         //返回操作结果
    12         return line;
    13     }

    然后我们会发现,里面的for循环一模一样,那么我们可以把这个单独封装成一个方法

     1 //获取PreparedStatement对象
     2     public static PreparedStatement getPreparedStatement(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;objs!=null&&i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //返回PreparedStatement对象
    10         return ppt;
    11     }

    那么这么封装以后,我们的查询和增删改的方法就可以简短一些

    然后关闭连接的方法依旧是关闭连接的方法,不变

    1 //关闭数据库连接
    2     public static void closeConnection() throws Exception {
    3         //关闭数据库连接
    4         conn.close();
    5     }

    那么这个DBTools就修改完成了,但是进行测试的时候发现出了问题,进行第一次数据库操作会把数据库给关闭连接了

    所以我们不能把数据库连接写在静态代码块中了,只能写一个方法了

    1 //创建一个方法连接数据库
    2     public static void getConnection() throws Exception {
    3         //创建连接对象
    4         conn = DriverManager.getConnection(url,user,pwd);
    5     }

    那么我们在getPreparedStatement这个方法中调用就OK了

  • 相关阅读:
    tableview加tap手势,cell点击无效了
    设置UISlider的ThumbImage,图片非常模糊, 使用代码生成图片就OK了
    思考阿里巴巴系的前端解决方案
    箭头函数和普通函数区别
    webpack
    this.$nextTick
    Node使用path和fs进行目录替换
    new操作符及原理
    javascript的设计模式发布订阅者模式
    vue2 和 vue3 对比
  • 原文地址:https://www.cnblogs.com/huajidafahao/p/11288871.html
Copyright © 2020-2023  润新知