并非人人是高手,并非人人是神仙,我也有不懂的地方,我也有不注意的技术问题,多交流多学习就是最好的提高方法

 

   其实对与初学者来说,进行的动态的查询语句拼接也不是那么好做的事情,就是做出来了,也未必是经得起考验的足够灵活好用的,未必是能拿得出手可以进行推广的,是否能拿得出就是其中的关键。

 

   今天检查公司的软件项目质量,发现有2个同事写的程序存在SQL注入攻击的漏洞,当然也不能怪罪人家,他们也是刚参加工作1-2年,还没有那么丰富的技术经验、安全意识,不会注意到自己编写的系统会有严重的安全漏洞。

   公司在宁波也有一个政府网站的项目,在做系统安全检查自动扫描时,也被查出了一些SQL注入攻击的漏洞,这也使得让我更加提高了系统是否存在安全漏洞的意识,当然我写的系统很少会有这类的漏洞,但是整个公司有几十号人在做开发公司,所以也难免别人不会犯错。

  

吉日'嘎拉”其中有单引号,很可能这个查询的页面就崩溃了出现了错误页面,或者跳转到出错页面了,若有这样的情况发生,几乎99.3721%都可以看做是有潜在的SQL注入攻击漏洞。

 

   防止这个错误的发生,从技术上应该说是要用“参数化的查询”,贴一些代码,给大家参考一下我的做法:




java 动态拼接sql查询条件工具类 sql语句动态拼接查询_jquery

java 动态拼接sql查询条件工具类 sql语句动态拼接查询_list_02

代码


  

#region 
    public DataTable Search(string folderId, string searchValue, Boolean deleteMark) 查询 
   
            /// 
     
   <summary> 
   
            /// 
    查询
            /// 
     
   </summary> 
   
            /// 
     
   <param name="folderId"> 
   目录 
   </param> 
   
            /// 
     
   <param name="searchValue"> 
   查询条件 
   </param> 
   
            /// 
     
   <param name="deleteMark"> 
   删除标志 
   </param> 
   
            /// 
     
   <returns> 
   数据表 
   </returns> 
   
             
   public 
    DataTable Search( 
   string 
    folderId,  
   string 
    searchValue, Boolean deleteMark)
        {
                // 
    一、这里是将Boolean值转换为int类型。 
   
                 
   int 
    delete  
   = 
    deleteMark  
   ? 
     
   1 
   :  
   0 
   ;

                // 
    二、这里是开始进行动态SQL语句拼接,字段名、表明都进行了常量定义,表名字段名发生变化时,很容易就知道程序哪里都调用了这些。 
   
                 
   string 
    sqlQuery  
   = 
     
   string 
   .Empty;
            sqlQuery     = 
     
   " 
    SELECT  
   " 
     
   + 
    BaseNewsTable.FieldId
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldFolderId
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldTitle
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldFilePath
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldFileSize
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldReadCount
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldDescription
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldCategoryCode
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldEnabled
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldDeleteMark
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldSortCode
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldCreateUserId
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldCreateUserRealname
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldCreateDate
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldModifyUserId
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldModifyUserRealname
                        + 
     
   " 
           , 
   " 
     
   + 
    BaseNewsTable.FieldModifyDate
                        + 
     
   " 
    FROM  
   " 
     
   + 
     
   this 
   .CurrentTableName
                        + 
     
   " 
    WHERE  
   " 
     
   + 
    BaseNewsTable.FieldDeleteMark  
   + 
     
   " 
    =  
   " 
     
   + 
    delete;

                // 
    三、我们认为 folderId 这个查询条件是安全,不是人为输入的参数,所以直接进行了SQL语句拼接 
   
                 
   if 
    ( 
   ! 
   String.IsNullOrEmpty(folderId))
            {
                sqlQuery     += 
     
   " 
    AND  
   " 
     
   + 
    BaseNewsTable.FieldFolderId  
   + 
     
   " 
    = ' 
   " 
     
   + 
    folderId  
   + 
     
   " 
   ' 
   " 
   ;
            }

                // 
    四、这里是进行参数化的准备,因为是多个不确定的查询参数,所以用了List。 
   
                List 
   < 
   DbParameter 
   > 
    dbParameters  
   = 
     
   new 
    List 
   < 
   DbParameter 
   > 
   ();

                // 
    五、这里看查询条件是否为空 
   
                searchValue  
   = 
    searchValue.Trim();
                if 
    ( 
   ! 
   String.IsNullOrEmpty(searchValue))
            {
                    // 
    六、这里是进行支持多种数据库的参数化查询 
   
                    sqlQuery  
   += 
     
   " 
    AND ( 
   " 
     
   + 
    BaseNewsTable.FieldTitle  
   + 
     
   " 
    LIKE  
   " 
     
   + 
    DbHelper.GetParameter(BaseNewsTable.FieldTitle);
                sqlQuery     += 
     
   " 
    OR  
   " 
     
   + 
    BaseNewsTable.FieldCreateUserRealname  
   + 
     
   " 
    LIKE  
   " 
     
   + 
    DbHelper.GetParameter(BaseNewsTable.FieldCreateUserRealname);
                sqlQuery     += 
     
   " 
    OR  
   " 
     
   + 
    BaseNewsTable.FieldContents  
   + 
     
   " 
    LIKE  
   " 
     
   + 
    DbHelper.GetParameter(BaseNewsTable.FieldContents);
                sqlQuery     += 
     
   " 
    OR  
   " 
     
   + 
    BaseNewsTable.FieldDescription  
   + 
     
   " 
    LIKE  
   " 
     
   + 
    DbHelper.GetParameter(BaseNewsTable.FieldDescription)  
   + 
     
   " 
   ) 
   " 
   ;
                
                    // 
    七、这里是判断,用户是否已经输入了% 
   
                     
   if 
    (searchValue.IndexOf( 
   " 
   % 
   " 
   )  
   < 
     
   0 
   )
                {
                    searchValue     = 
     
   " 
   % 
   " 
     
   + 
    searchValue  
   + 
     
   " 
   % 
   " 
   ;
                }

                    // 
    八、这里生成支持多数据库的参数 
   
                    dbParameters.Add(DbHelper.MakeInParam(BaseNewsTable.FieldTitle, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(BaseNewsTable.FieldCreateUserRealname, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(BaseNewsTable.FieldContents, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(BaseNewsTable.FieldDescription, searchValue));
            }

                // 
    九、这里是将List转换为数组,进行数据库查询 
   
                 
   return 
    DbHelper.Fill(sqlQuery, dbParameters.ToArray());
        }
            #endregion


 

对以上代码进行一下简单的点评:

优点有如下:

    1:支持多数据库。

    2:dbParameters.Add,非常灵活,可以动态组织多个查询条件条件,想要几个参数就要几个参数,最后又巧妙的用了 dbParameters.ToArray(),这个是值得学习的。

    3:函数的命名、注释、参数的大小写比较规范。

    4:函数的注释写得很棒,对初学者学习模仿起了一个好榜样。

"%") 也想得比较深入,有些专业人事查询时,可能已经输入了%。

    6:表名、表字段都进行了定义,若后期表名、表字段发生了变化,程序不会有未知的错误,很容易在编码阶段就发现错误,在软件开发初期,表名、字段名变来变去是很常见的事情,若是好几个人开发的,又经常变来变去的,若是当时没控制好,后期就会乱套。

    7:SQL语句拼接时,没有用 WHERE 1=1 AND , 而是巧妙的运用了 DeleteMark 字段,是值得学习的。

    8:SQL语句中关键字都进行了大写,是比较符合行业规范的,大家也值得参考。

    9:不管如何,对自己写的每行代码,每行注释,都有了深入的讲解、深入的认识,这是大家值得学习的,若哪里写得不好,有错就改的精神,分享的精神是值得学习的。

  10:先关注好身边的事情、才能关注网上的事情,是大家值得学习的,别总是有过于远大的理想,过于理想化的梦想,把身边的事情都做好,把身边的同事都关注好,就是干得最出色最及格了,这个务实的精神也是大家值得学习的。

  11:  查询代码思路严谨得有些过分,实在是过分,区区一个动态查询居然分了9个步骤来实现,思路细腻严谨得让人实在是佩服啊,不佩服不行啊,菜鸟程序员的骄傲、学习模仿的楷模,呵呵。

 

  先就写到这里吧,再夸下去,估计很多人都要吐了。