这是一位师哥写的类.哈哈. 之前我是一直用参数化的,看这个写起来比较快.大家感觉怎么样? 有没有其他的BUG呢
 public static void Insert(ServiceInfo entity)
        {
            DBLayer.ExeSql(GetInsertSql(entity));
            return;
        }public static string GetInsertSql(ServiceInfo entity)
        {
            StringBuilder strSql = new StringBuilder("Insert ServiceInfo (");            
            strSql.Append("userid,");
            strSql.Append("serviceid,");
            strSql.Append("servicename,");
            strSql.Append("companyid,");
            strSql.Append("companyname,");
            strSql.Append("worktime,");
            strSql.Append("tellphone,");
            strSql.Append("address,");
            strSql.Append("consume,");
            strSql.Append("busLine,");
            strSql.Append("carbit,");
            strSql.Append("img,");
            strSql.Append("contest,");
            strSql.Append("province,");
            strSql.Append("city,");
            strSql.Append("country,");
            strSql.Append("support,");
            strSql.Append("demand,");
            strSql.Append("price,");
            strSql.Append("Mark,");
            strSql.Append("shenhe,");
            strSql.Append("img)");
            strSql.Append(" values (");
           
            strSql.Append("'" + entity.userid + "',");
            strSql.Append("'" + entity.serviceid + "',");
            strSql.Append("'" + entity.servicename + "',");
            strSql.Append("'" + entity.companyid + "',");
            strSql.Append("'" + entity.companyname + "',");
            strSql.Append("'" + entity.worktime + "',");
            strSql.Append("'" + entity.tellphone + "',");
            strSql.Append("'" + entity.address + "',");
            strSql.Append("'" + entity.consume + "',");
            strSql.Append("'" + entity.busLine + "',");
            strSql.Append("'" + entity.carbit + "',");
            strSql.Append("'" + entity.img + "',");
            strSql.Append("'" + entity.contest + "',");
            strSql.Append("'" + entity.province + "',");
            strSql.Append("'" + entity.city + "',");
            strSql.Append("'" + entity.country + "',");
            strSql.Append("'" + entity.support + "',");
            strSql.Append("'" + entity.demand + "',");
            strSql.Append("'" + entity.price + "',");
            strSql.Append("'" + entity.Mark + "',");
            strSql.Append("'" + entity.shenhe + "',");
            strSql.Append("'" + entity.img + "')");
            return strSql.ToString();
        } public static void ExeSql(string sql)
        {
            if (Func.filterSql(sql) == 1)
            {
                return ;
            }
            SqlConnection conn = new SqlConnection(ConnectionString);
            SqlCommand cmd = new SqlCommand(sql, conn);
            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();
        }  public static int filterSql(string sSql)
        {
            int srcLen, decLen = 0;
            sSql = sSql.ToLower().Trim();
            srcLen = sSql.Length;
            sSql = sSql.Replace("exec ", "");
            sSql = sSql.Replace("drop ", "");
            sSql = sSql.Replace("master ", "");
            sSql = sSql.Replace("truncate ", "");
            sSql = sSql.Replace("declare ", "");
            sSql = sSql.Replace("create ", "");
            sSql = sSql.Replace("xp_", "no");
            sSql = sSql.Replace("net user", "");
            sSql = sSql.Replace("xp_cmdshell", "");
            sSql = sSql.Replace("net localgroup administrators", "");
            sSql = sSql.Replace("master.dbo.xp_cmdshell", "");
            sSql = sSql.Replace("/add", "");
            decLen = sSql.Length;
            if (srcLen == decLen) return 0; else return 1;
        }

解决方案 »

  1.   

    一般都是调用sp,而不是执行sql语句
      

  2.   

    strinbuilder替换的确有优势,速度较string替换快,但问题是字符串中有那些关键字是很正常的,替换后的文字还能叫人话吗?而且替换速度再快也要耗费时间进行吧,难道比建立几个参数对象然后直接发送到服务器快吗?在托管堆中建立对象也只是初始化几个字段(自身字段与开销字段)而已,不用替换这种遍历操作啊.
    不过建立对象多的话肯定要给GC造成压力,不过我想得肯定大于失的.
      

  3.   

    只要你是拼SQL的,无论的玩什么花样,都会被注入。
      

  4.   

    我用也是传sql语句,但不是你那种写法,我的写法如下:
     SqlCommand cmd = new SqlCommand();
                photoParms[0].Value = photo.Pho_Code;
                photoParms[1].Value = photo.Pho_UserId;
                photoParms[2].Value = photo.Pho_Time;
                photoParms[3].Value = photo.Pho_ID;
                     parms = new SqlParameter[] { 
                        new SqlParameter(PARM_Pho_Code, SqlDbType.BigInt),
                        new SqlParameter(PARM_Pho_UserId, SqlDbType.VarChar,20),
                        new SqlParameter(PARM_Pho_Time, SqlDbType.DateTime), 
                        new SqlParameter(PARM_Pho_ID, SqlDbType.BigInt)};
      

  5.   

    存储过程就一定 不被sql注入吗???????????????????????
      

  6.   

    不知有没有人回答一下22楼的问题以前写ASP的时候,用这个,没发现问题但现在太多版本的防注入代码,对这个又有点怀疑了。不知这个方式能不能被绕过
      

  7.   

    单引号的问题都还没考虑,难道没问题!
    如果是插入操作,最好还是用存储过程或者Parameter public override void ExeSql(string strSql, List<string> paramNames, List<object> objParamValues)
            {
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = this._conn;
                cmd.CommandText = strSql;
                if ((paramNames != null) && (paramNames.Count != objParamValues.Count))
                {
                    throw new DataFactory.GoberlDataDll.MyException.ParamValueNotMatchParamNameException();
                }
                //添加ParamItem
                if (paramNames != null)
                {
                    for (int i = 0; i < paramNames.Count; i++)
                    {
                        if (objParamValues[i].GetType().ToString() == "System.DateTime")
                        {
                            SqlParameter p = new SqlParameter();
                            p.ParameterName = paramNames[i];
                            p.SqlDbType = SqlDbType.Date;
                            p.Value = objParamValues[i];
                            cmd.Parameters.Add(p);
                        }
                        else
                            cmd.Parameters.AddWithValue(paramNames[i], objParamValues[i]);
                    }
                }
                else
                {
                    throw new DataFactory.GoberlDataDll.MyException.ParamValueNotMatchParamNameException();
                }            try
                {
                    this.OpenCon();
                    this.BeginTrans();
                    cmd.Transaction = this._trans;
                    cmd.ExecuteNonQuery();
                    this.CommitTrans();
                }
                catch (Exception exp)
                {
                    this.RollbackTrans();
                    throw exp;
                }
                finally
                {                cmd.Dispose();
                    this.CloseCon();
                    this._conn.Dispose();
                }        }
      

  8.   

    存储过程为什么能防止注入? 其实是因为存储过程中的变量是有类型的,类型不对,不会让你通过运行的。而且存储过程中不存在字符串引号的问题,你传入',我就搜索'所以可以从根本上避免SQL注入问题!SqlParameter的道理和他一样!不过我还是做提前判断,如果是ID号,不是数字的立即导向错误页面,免的你再去搜索数据库浪费资源!
      

  9.   

    使用代码生成器生成SQL,不建议你这么过滤字符,建议使用参数SQL或存储过程
      

  10.   

    现在很少 有人用SQL语句吧 都是存储过程了
      

  11.   

    传入参数有两种:int, string int型参数拼接: 
    string sql = "select * from table1 where id=" + int.Parse(Request["id"]); string型参数拼接: 
    string sql = "select * from table1 where name='" + Request["name"].Replace("'","''") + "'"; ======== 
    请问谁可以注入?
      

  12.   

    存储过程参数的个数受限制,参数的类型受限制,如果同时使用SqlParameter
    是能够防止SQL注入的,再说使用类,对传入的数据惊醒类型匹配,更能防止非法数据了。