zoukankan      html  css  js  c++  java
  • 源码分析 iBatis简单动态SQL处理($$)

      在iBatis中对于$param$的处理方法是怎么样的呢?下面将通过源码解读具体的处理逻辑

    public class SimpleDynamicSql implements Sql {
    
      private static final Probe PROBE = ProbeFactory.getProbe();
    
      // 分词字符
      private static final String ELEMENT_TOKEN = "$";
    
      private String sqlStatement;
    
      private SqlMapExecutorDelegate delegate;
    
      public SimpleDynamicSql(SqlMapExecutorDelegate delegate, String sqlStatement) {
        this.delegate = delegate;
        this.sqlStatement = sqlStatement;
      }
    // 获取sql
      public String getSql(StatementScope statementScope, Object parameterObject) {
        return processDynamicElements(sqlStatement, parameterObject);
      }
    
      public ParameterMap getParameterMap(StatementScope statementScope, Object parameterObject) {
        return statementScope.getParameterMap();
      }
    
      public ResultMap getResultMap(StatementScope statementScope, Object parameterObject) {
        return statementScope.getResultMap();
      }
    
      public void cleanup(StatementScope statementScope) {
      }
    // 如果sql不为null且存在$则认为是简单动态sql
      public static boolean isSimpleDynamicSql(String sql) {
        return sql != null && sql.indexOf(ELEMENT_TOKEN) > -1;
      }
    
      private String processDynamicElements(String sql, Object parameterObject) {
      // 新建一个分词工具
        StringTokenizer parser = new StringTokenizer(sql, ELEMENT_TOKEN, true);
        StringBuffer newSql = new StringBuffer();
    
        String token = null;
        String lastToken = null;
    	//如果sql中含有$
        while (parser.hasMoreTokens()) {
    	// 获取第一个分词对象
          token = parser.nextToken();
    		//如果最后一个分词对象等于$
          if (ELEMENT_TOKEN.equals(lastToken)) {
            if (ELEMENT_TOKEN.equals(token)) {
              newSql.append(ELEMENT_TOKEN);
              token = null;
            } else {
    // 如果lastToken=$且token不等于$则将token替换为token对应的属性值,默认为空字符串
              Object value = null;
              if (parameterObject != null) {
                if (delegate.getTypeHandlerFactory().hasTypeHandler(parameterObject.getClass())) {
                  value = parameterObject;
                } else {
                  value = PROBE.getObject(parameterObject, token);
                }
              }
              if (value != null) {
                newSql.append(String.valueOf(value));
              }
              //获取下一个分词,如果下一个分词不是$则抛出异常
              token = parser.nextToken();
              if (!ELEMENT_TOKEN.equals(token)) {
                throw new SqlMapException("Unterminated dynamic element in sql (" + sql + ").");
              }
              token = null;
            }
    		// 如果最后一个分词对象不等于$
          } else {
    	     //如果当前分词不是$在将当前分词追加在newSql中
            if (!ELEMENT_TOKEN.equals(token)) {
              newSql.append(token);
            }
    		// 如果当前分词等于$则不做任何处理
          }
    		//将当前分词赋值给最后一次分词
          lastToken = token;
        }
    
        return newSql.toString();
      }
    
    
    }

     例如:select * from $a$,param={a,tax_refund_info}的分词结果是:


    select * from

    $

    a

    $

    第一次循环:
      lastToken=null,
      token=select*from
     
      lastToken!=$

      newSql=select* from
     
     lastToken=select*from
     
    第二次循环
      lastToken=select * from
      token=$
     //doNothing
     lastToken=$
    第三次循环
      lastToken=$
      token=a;
     
      newSql=select * from tax_refund_info
     
     第三次循环
       lastToken=a;
       token=$
       //doNothing
       newSql=select * from  tax_refund_info
      
     我们可以发现这样的查询完全无法防止SQL注入攻击。

  • 相关阅读:
    ES6 Promise用法讲解
    NPM使用介绍
    Docker学习系列(二):Docker三十分钟快速入门(上)
    Spring Cloud学习(一)
    胖ap和瘦ap的区别
    论网络知识的重要性
    2018 发发发发
    sikuli--前端自动化操作的神器
    更改MySQL数据库的编码为utf8mb4
    数据库mysql的常规操作
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797774.html
Copyright © 2011-2022 走看看