Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免C#桌面应用程序中无存储过程的SQL注入_C#_Sql - Fatal编程技术网

如何避免C#桌面应用程序中无存储过程的SQL注入

如何避免C#桌面应用程序中无存储过程的SQL注入,c#,sql,C#,Sql,我正在使用MS SQL server数据库开发C#桌面应用程序。 我保持不同的类如下连接到数据库 using System.Data.Odbc; class DataBaseConnection { private OdbcConnection conn1 = new OdbcConnection(@"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "Pwd=otdata@123;"); //"DSN=Ot_DataODBC;" + "

我正在使用MS SQL server数据库开发C#桌面应用程序。 我保持不同的类如下连接到数据库

 using System.Data.Odbc;

class DataBaseConnection
    {
        private OdbcConnection conn1 = new OdbcConnection(@"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "Pwd=otdata@123;"); //"DSN=Ot_DataODBC;" + "Uid=sa;" +  "Pwd=otdata@123;"

        //insert,update,delete
        public int SetData(string query)
        {
            try
            {
                conn1.Open();
                OdbcCommand command = new OdbcCommand(query, conn1);
                int rs = command.ExecuteNonQuery();
                conn1.Close();
                return rs;
            }
            catch (Exception ex)
            {
                conn1.Close();
                throw ex;
            }
        }
        //select
        public System.Data.DataTable GetData(string sql)
        {
            try
            {
                conn1.Open();
                OdbcDataAdapter adpt = new OdbcDataAdapter(sql, conn1);
                DataTable dt = new DataTable();
                adpt.Fill(dt);
                conn1.Close();
                return dt;
            }
            catch (Exception ex)
            {
                conn1.Close();
                throw ex;
            }
        }

   }
在我需要的地方,我对那个数据库连接类创建对象,并调用get和set方法作为需要

例如----

  • 是否允许从该方法执行SQl注入
  • 如何避免不使用存储过程的sql注入

您可以像在其他任何地方一样避免SQL注入—将SQL代码与数据分开。如果您坚持让接口仅基于传入字符串,那么您就无法做到这一点

我会去掉你的包装器类(它只是模糊了一些东西),并利用它在你的查询旁边传递数据


(我还建议您在各种数据库对象周围使用
语句,而不是当前的手动操作,以确保调用
Close
,这也会通过重新抛出异常略微破坏良好的错误处理)


(另外,我建议您在任何需要的地方使用新的
OdbcConnection
对象,而不是试图共享一个对象-只要多线程的概念进入您的代码库,您就会感谢您这样做了,这在当今是不可避免的)

最重要的技术是使用以下方式绑定变量:

 string SaveNewEmp = 
   "INSERT INTO Employee  (Service_ID, Title, Name, Initials) VALUES (?, ?, ?, ?)";

command.Parameters.Add("@servicenumber", OdbcType.Int).Value = ...;
command.Parameters.Add("@title", OdbcType.VarChar).Value = ...;
command.Parameters.Add("@fullname ", OdbcType.VarChar).Value = ...;
command.Parameters.Add("@initials ", OdbcType.VarChar).Value = ...;
通常,这也会带来性能提升,您不必关心报价,想象一下
标题将是
今天是您的日子
——这将与您的方法失败

更新

使用参数列表很简单:

public int SetData(string query, OdbcParameterCollection parList)
{
   ...  
   OdbcCommand command = new OdbcCommand(query, conn1);
   OdbcCommand.Parameters.Add(parList);
}


var parList = new OdbcParameterCollection();
parList.Add("@servicenumber", OdbcType.Int);
parList.Add("@title", OdbcType.VarChar);
...
int ret = SetData(query, parList);
但是,我没有测试它,也许你必须运行

foreach ( OdbcParameter aPar in parList ) { 
    OdbcCommand.Parameters.Add(aPar);
}

使用
List

Damien\u,不信者的答案基本上是好的,但我想改进/修改它

您还可以更改
SetData
GetData
方法,并为它们添加一个参数数组(尽管我与他/她分享了摆脱该类的想法,但您可以将其抽象化以创建更具体的DAL类)

避免SQL注入的唯一要求是使用参数,或者使用存储过程(由于问题要求而不可能),或者使用代码中编写的查询

如果执行的SQL(在编码查询或存储过程中)确实使用了
sp\u execute\u SQL
或类似的方法,则即使使用参数,也有可能进入SQL注入。如果在查询中使用
sp\u execute\u sql
,请确保避免使用用户提供的信息写入查询。您可以将sp_execute_sql函数的参数设置为第二个可选参数。

这是一个反复出现的问题(至少在过去20年中),但我坚信我有了一个新的答案。。。使用QueryFirst。您获得了存储过程的优势,但您的SQL存在于应用程序中的.SQL文件中,并随应用程序进行版本控制。只需在SQL中引用参数即可创建参数。将为您生成所有参数处理代码。您(和您的团队)必须使用参数,因为没有其他方法。消除了做不安全事情的可能性。还有很多其他优点:您可以在真实环境中编辑sql,并使用语法验证和intellisense。您的查询不断地针对数据库进行集成测试,并重新生成它们的包装代码。所有错误都会在键入时捕获,或在保存.sql时捕获,或在最后一种情况下,在生成时捕获。理论上,数据访问不存在运行时错误

通常,严格性是以简单性/易用性为代价的。这种方法比传统的字符串中sql方法更严格、更易于使用。语言和平台的可移植性即将到来。将sql查询从windows上的C#项目拖放到linux或mac上的Node express应用程序中,然后重新生成,您将得到一个typescript包装器,而不是一个C#包装器。这应该引起人们的注意

免责声明:我写了QueryFirst。 下载。
小博客。

是的,在上面的查询上进行SQL注入非常容易。1答案。参数和这一点在今天是并行的,看看为什么使用Odbc代替Sql.Net驱动程序(例如SqlConnection)?使用@P.Pat和Damien_不信者提到的参数化查询。为什么不使用一些ORM?但是,我如何在“DataBaseConnection类”中使用参数呢?我使用这个类在我的程序中获取和设置数据,通过这个类将150多个不同的quary解析到数据库中?我如何根据不同的quary自定义参数?有人能帮忙吗@PPat@GayanChinthakaDharmarathna我建议您学习存储过程,看看是否可以在当前的DBMS中实现它。它还可以防止sql注入。但是,我如何在“DataBaseConnection类”中使用参数呢?我在我的程序中使用这个类获取和设置数据,通过这个类将150多个不同的方解析到数据库中?我如何根据不同的方自定义参数?您可以在外部准备一个参数数组(或
List(T)
,等等),并将这个数组作为参数传递给DataBaseConnection构造函数。然后在循环中分配参数。你能给我推荐一个使用数组或列表(T)的例子吗?
foreach ( OdbcParameter aPar in parList ) { 
    OdbcCommand.Parameters.Add(aPar);
}