zoukankan      html  css  js  c++  java
  • PreparedStatement防止SQL注入

    防止sql注入的方式一般从两个方面下手,一个是代码方面。一个是数据库方面。在数据库方面比如mybatis的方式使用 #{} 就可以防止注入。

    今天我们只谈谈PreparedStatement如何防止SQL注入。

    PreparedStatement内置了SQL预备处理的能力

    String sql= "select * from users where username=? and password=?;
    PreparedStatement preState = conn.prepareStatement(sql);
    preState.setString(1, userName);
    preState.setString(2, password);
    ResultSet rs = preState.executeQuery();
    select * from users where username=? and password=?这个SQL会进行预编译,再填充参数的,使用setString方法替换?代表的参数。
    但是如果不用问号代替,直接通过参数拼接SQL,那么预编译就没有意义,那就还是没有防止SQL注入。
    比如
    select * from tb_name = '随意' and passwd = '' or '1' = '1';
    这个时候passwd输入的参数是: ' or '1' = '1

    更有甚者直接输入
    select * from tb_name = '随意' and passwd = '';drop table tb_name;
    直接将passw的参数改成: ';drop table tb_name;

    不过一般没有使用预编译的系统网站会通过拦截特殊字符的方式防止sql注入的。

    下面我们改进下上面的代码,让替换的方式更加灵活。
      public int update(String sql, List<?> params)
      {
        PreparedStatement ps = null;
        try {
          Connection conn = POContext.getConnection(this.dbName, this.txnName, this.timeOut);
        
          ps = conn.prepareStatement(sql);
          if ((params != null) && (params.size() > 0)) {
            for (int i = 0; i < params.size(); i++) {
              setParam(ps, i + 1, params.get(i));
            }
          }
          return ps.executeUpdate();
        } catch (Exception e) {
          throw new DAOException("update error!", e);
        } finally {
          clean(null, ps);
        }
      }
    public void setParam(PreparedStatement ps, int idx, Object obj) {
        try { if ((obj instanceof Date)) {
            ps.setTimestamp(idx, new Timestamp(((Date)obj).getTime()));
            return;
          }
          if ((obj instanceof Blob)) {
            ps.setBlob(idx, (Blob)obj);
            return;
          }
          if ((obj instanceof Clob)) {
            ps.setClob(idx, (Clob)obj);
            return;
          }
          if ((obj instanceof BigDecimal)) {
            ps.setBigDecimal(idx, (BigDecimal)obj);
            return;
          }
          if ((obj instanceof BigInteger)) {
            ps.setBigDecimal(idx, new BigDecimal((BigInteger)obj));
            return;
          }
          if ((obj instanceof Boolean)) {
            ps.setInt(idx, ((Boolean)obj).booleanValue() ? 0 : 1);
            return;
          }
          ps.setObject(idx, obj);
        } catch (SQLException e) {
          this.logger.error("ps set params error!", e);
          throw new DAOException("ps set params error!", e);
        }
      }
    

      这样修改的话,替换?的方式更加灵活,只需要在List<?> params传参时,注意对应位置,不需要再每个PreparedStatement的setObject方法的第一个参数前加上替换问号的位子,

    以及注意参数类型了 

  • 相关阅读:
    夜神安卓模拟器
    Jmeter分布式压力测试环境配置
    Jmeter接口测试数组变量传值
    Jmeter测试JDBC
    BeanShell PreProcessor数据base64加密
    数据库锁表查看与解锁
    Python对数据库进行操作
    Jmeter正则表达式提取器详解
    将博客搬至CSDN
    web开发学习笔记(四)Ajax的使用方法
  • 原文地址:https://www.cnblogs.com/songcuiting/p/8950192.html
Copyright © 2011-2022 走看看