如何避免C#桌面应用程序中无存储过程的SQL注入
我正在使用MS SQL server数据库开发C#桌面应用程序。 我保持不同的类如下连接到数据库如何避免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;" + "
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注入
(我还建议您在各种数据库对象周围使用
和语句,而不是当前的手动操作,以确保调用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);
}