请问各位,如果项目弄成三层结构的话,那么如何防止SQL注入呢?
数据层一般都是固定的吧?也就是说:不用管什么SQL语句(分为查询和插入(更改)两种)用的都是一个方法,但是这样的话,如何来防止sql注入呢?
就是这样:
数据层:
public DataSet Select(string sSQL)
{
   SqlConnection con=new SqlConnection("连接字符串");//建立数据库连接
   SqlDataAdapter adr=new SqlDataAdapter(sSQL,con);
   DataSet ds=new DataSet();
   adr.Fill(ds);
   return(ds);
}
public int Execute(string sSQL)
{
   SqlConnection con=new SqlConnection("连接字符串");//建立数据库连接
   con.Open();
   SqlCommand cmd=new SqlCommand(sSQL,con);
   return cmd.ExecuteNonQuery();
}
然后在逻辑层,比如说添加一个员工(或者其他的所有的修改和增加的操作),就调用数据层的Execute(“写好的SQL语句作为参数传递”);而选择的话,就调用数据层的Select(“写好的SQL语句作为参数传递");
可是这样的话,请问大家,该如何防止SQL注入呢?不会是过滤危险字符吧?如果过滤的话,那一些技术类的文章可能就显示不出来了,而且,三层结构如何来进行原子性操作呢?

解决方案 »

  1.   

    考虑一下用存储过程或者使用参数吧,这样可以在一定程度上避免SQL注入。
      

  2.   

    大哥我没说做多少层,我是在向大家请教,做三层如何实现防注入和原子性操作的问题。我不知道不防范做一百层也没用啊?
    我知道用参数和存储过程可以防止SQL注入,但是用参数的话,每个SQL所带的参数是不一样的,那么不会把每个语句在分开对待处理吧?那样的话,我觉得这底层的数据层就没太大的意义了。
    请高手支招。
      

  3.   

    大哥我没说做多少层,我是在向大家请教,做三层如何实现防注入和原子性操作的问题。我不知道不防范做一百层也没用啊? 
    我知道用参数和存储过程可以防止SQL注入,但是用参数的话,每个SQL所带的参数是不一样的,那么不会把每个语句在分开对待处理吧?那样的话,我觉得这底层的数据层就没太大的意义了。 
    请高手支招。
      

  4.   

    用什么方法屏蔽啊?Replace?如果输入的内容是一些数据库类的文章,那么恐怕文章中的'、select就都显示不出来了吧?
      

  5.   

    public DataSet Select(string sSQL) 

    sSQL = sSQL.replace("'","");
      SqlConnection con=new SqlConnection("连接字符串");//建立数据库连接 
      SqlDataAdapter adr=new SqlDataAdapter(sSQL,con); 
      DataSet ds=new DataSet(); 
      adr.Fill(ds); 
      return(ds); 

    public int Execute(string sSQL) 

    sSQL = sSQL.replace("'","");
      SqlConnection con=new SqlConnection("连接字符串");//建立数据库连接 
      con.Open(); 
      SqlCommand cmd=new SqlCommand(sSQL,con); 
      return cmd.ExecuteNonQuery(); 

    哈哈,这样是不是就会好一点呢??
    要不再加上过滤 --??
      

  6.   

    就拿你写的那两个方法来说 参数里面完全可以添加一个sql参数的数组啊 string完全可以传递存储过程的名字啊 这样的话方法也还是没有变化的 况且 只传string和只返回影响行数的int值 在一些特定的sql操作中 是根本不能满足需要的 如果谁说 他的项目里面的数据操作的select就铁定只用一种方法了 那我估计他做不下去的!~
      

  7.   

    @whb147
    这个过滤'和--不是太好的解决方法吧? 参数里面完全可以添加一个sql参数的数组啊
    ============
    这个倒是考虑过,不过觉得还是有点儿麻烦,所以在网上来看看大家有没有什么别的方法?string完全可以传递存储过程的名字啊
    =============
    这个就和一层的的一样了吧?传存储过程名不还是要给他传参数吗?
    或许我和你理解的不一样?
      

  8.   

    额..还有..数组是说顺嘴了 其实我的意思是提供一个sql参数的集合
      

  9.   

    个人愚见:
    如果能正确处理单引号问题,SQL注入问题应该就可以解决了。
    解决办法:运用CommandParameter屏蔽:这个方法可以应对相当一部分SQL注入,但是倘若后台数据库中需要执行诸如EXEC @SQLString 的命令,那么还需要专门针对单引号作过滤(比如将一个单引号替换为两个单引号)
      

  10.   

    运用了CommandParameter,对于后台数据库来说应该可以屏蔽掉诸如delete,update,drop,truncate table等破坏性的攻击命令。
    此外还需要合理运用异常处理可使程序更为健壮地运行,见笑了!!!
      

  11.   

    静态发布解决全部问题!~~xml+xsl
      

  12.   


    //@name对应你存储过程中的参数名
     SqlParameter[] par = new SqlParameter[1];
            par[0] = new SqlParameter("@name", SqlDbType.VarChar, 20);
            par[0].Value = use.name;
            return dal.NonQuery("存储过程名", par);存储过程传参数就这样传给数据层了啊
      

  13.   

    楼主这样并没有起到一个分层的作用..跟直接调用sql是一样的.你这样做只是起到一个封装的作用.并不是实际意义上面的分层.真正的三层中是不会传一个sql语句来作为参数的...而是传一个对像.
      

  14.   

    过滤字符串是无法阻止sql注入的,测试以下代码create table tttest(id int)
    go
    declare @s varchar(100)
    set @s= char(100)+char(114)+char(111)+char(112) + ' table tttest'
    exec(@s)select * from tttest
      

  15.   

    1.一般UI层和业务层就不应该见到SQL语句
    2.穿参可以传参数数组你可以看看我昨天回的一个帖子的修改
    http://topic.csdn.net/u/20080613/00/3b28acd0-e68e-4a01-9370-d437021133de.html实际应用,也有可能使用的是IDataParameter
      

  16.   

    1.一般UI层和业务层就不应该见到SQL语句 
    =======
    业务层也不见到SQL语句吗?可是那样的话,这数据层岂不是就很麻烦了吗?
    能详细的解释一下吗?最好是给个例子,谢谢了。我看看您给的那个链接啊!
      

  17.   

    恩,高歌您好,我刚才看了看那个帖子,和13楼和14楼一样,是将SqlParamter也传给了数据层了对吧?
    暂且先这样吧,只是这个数据的原子性操作,该怎么办呢?
    也就是说:如果表1的数据和表2的数据必须同时删除,该怎么办呢?
    请指教!
      

  18.   

    我晕 这个解释....
    传了对象最后怎么跟数据库进行交互的??照你的说法分了层就不用sql了??你数据层里面写的都是啥???
      

  19.   

    每个参数都要过滤的时候,你就弄个传递sqlparameter数组。在SQL层循环拆这个参数数组赋值的时候,就统一一个个过滤就可以了。不过感觉有些真的没必要过滤。这样做性能上感觉很浪费
      

  20.   


    太吓人了。竟然把tttest表删掉了。
      

  21.   

    呵呵..尽量不要拼接sql,就算在存储过程中也尽量少拼接.因为只要你拼接.就可能会有问题对于sql的参数一定要参数化,更不能去拼接!
      

  22.   

    新建一个用户,不用sa呢?比如用sbCREATE LOGIN sb 
        WITH PASSWORD = '1234';
     
    CREATE USER sb FOR LOGIN sb;
     
    grant select to sb;
    grant execute to sb;go
    create proc ptest as
    begin
    select * from aa
    --delete from aa
    end 这样就只能用select语句,或者存储过程了,直接运行delete之类的就会报错
      

  23.   

    这是我写的一个初步过滤的public String convertQuotationMarks(String oldString)
            {
                string newString = oldString;            while (oldString.IndexOf("'") >= 0)
                {
                    newString = oldString.Replace("'", "’");                oldString = newString;
                }
                string sqlstr = "and|exec|insert|select|delete|update|count|--|char|master|drop|truncate|declare";
                string[] anysqlstr = sqlstr.Split('|');
                foreach (string ss in anysqlstr)
                {
                    if (newString.IndexOf(ss) >= 0)
                    {
                        newString = "NULL";
                    }
                }
                return newString;        }
      

  24.   

    决不用直接拼接的SQL,一般是用参数绑定,除非是一些固定的,我们已经写好的可信任的SQL语句,或者对于拼接好的SQL绝对的可以信息,如
    select * from table where [id]=var
    其中,var我们可以绝对信任是数字,不可能会有injetion问题。