参数化查询与SQL注入

我是新来的Asp.net,我刚刚开始与类工作。 我最近创build了一个类来处理我的大部分SQL查询,这样我就不必重复build立所有文件的新连接。

我创build的方法之一是将SQL查询作为参数,并返回结果。 我知道我应该使用参数化查询来避免SQL注入。 我的问题是,我作为一个stringparameter passing查询时如何做到这一点?

例如,以下是我将要调用的方法:

public static DataTable SqlDataTable(string sql) { using (SqlConnection conn = new SqlConnection(DatabaseConnectionString)) { SqlCommand cmd = new SqlCommand(sql, conn); cmd.Connection.Open(); DataTable TempTable = new DataTable(); TempTable.Load(cmd.ExecuteReader()); return TempTable; } } 

所以从另一个文件我想使用这样的方法:

 DataTable dt = new DataTable(); dt = SqlComm.SqlDataTable("SELECT * FROM Users WHERE UserName='" + login.Text + "' and Password='" + password.Text + "'"); if (dt.Rows.Count > 0) { // do something if the query returns rows } 

这工作,但仍然容易受注射吗? 有没有一种方法可以将variables传递给string作为参数? 我知道我可以做到这一点,如果我为查询创build一个新的SQLCommand对象,并使用Parameters.AddWithValue,但我希望我所有的SQL命令在单独的类。

这工作,但仍然容易受注射吗?

是的,你的代码恐怕很容易受到SQL注入的影响。

我知道我应该使用参数化查询来避免SQL注入。

哦,绝对是的。

我的问题是,我作为一个stringparameter passing查询时如何做到这一点?

你不应该将查询作为stringparameter passing。 相反,你应该传递查询作为string参数包含占位符和这些占位符的值:

 public static DataTable SqlDataTable(string sql, IDictionary<string, object> values) { using (SqlConnection conn = new SqlConnection(DatabaseConnectionString)) using (SqlCommand cmd = conn.CreateCommand()) { conn.Open(); cmd.CommandText = sql; foreach (KeyValuePair<string, object> item in values) { cmd.Parameters.AddWithValue("@" + item.Key, item.Value); } DataTable table = new DataTable(); using (var reader = cmd.ExecuteReader()) { table.Load(reader); return table; } } } 

然后像这样使用你的function:

 DataTable dt = SqlComm.SqlDataTable( "SELECT * FROM Users WHERE UserName = @UserName AND Password = @Password", new Dictionary<string, object> { { "UserName", login.Text }, { "Password", password.Text }, } ); if (dt.Rows.Count > 0) { // do something if the query returns rows } 

你所要做的事情是非常合乎逻辑的,我可以理解你为什么要实现这个目标。 然而,你试图做的事情是非常危险的,对于ASP.NET而言,你可能并不知道有很多其他的选项可以让你pipe理你的数据变得更容易和更安全。

@iamkrillin暗示了一种这样的技术 – 对象关系映射(ORM)。 .NET框架实际上拥有称为entity framework的ORM的一stream支持。 我相信他build议你看看ORM的原因是因为你的devise本质上与ORM的工作方式非常相似。 它们是抽象类,代表数据库中的表,可以使用LINQ轻松查询。 LINQ查询自动参数化,并减轻pipe理查询安全性的压力。 它们可以随时生成SQL(就像将string传递给数据访问类时一样),并且在返回数据(数组,列表等)的方式上更加灵活。

然而,ORM的一个缺点是它们的学习曲线非常陡峭。 一个更简单的选项(虽然比EF旧一点)将是使用types化数据集。 types化数据集比创buildORM更容易创build,而且通常更容易实现。 虽然不像ORM那样灵活,但他们以一种简单,安全和已经解决的方式完成了你想要做的事情。 幸运的是,当ASP.NET首次推出专注于input数据集的培训video时,有许多高质量免费video/教程可以帮助您快速启动和运行。

你走在正确的轨道上,我也已经做了你自己也在寻找的东西。 但是,不是只传递一个string到你的函数中,而是传递一个SQL Command对象…这样,你可以正确地构build出所有的命令和参数,然后说…在这里,运行这个,它准备好了。 就像是

 public static DataTable SqlDataTable(SqlCommand cmd) { using (SqlConnection conn = new SqlConnection(DatabaseConnectionString)) { cmd.Connection = conn; // store your connection to the command object.. cmd.Connection.Open(); DataTable TempTable = new DataTable(); TempTable.Load(cmd.ExecuteReader()); return TempTable; } } public DataTable GetMyCustomers(string likeName) { SqlCommand cmd = new SqlCommand(); cmd.CommandText = "select * from SomeTable where LastName like "@someParm%"; cmd.Parameters.Add( "whateverParm", likeName ); // don't have SQL with me now, guessing syntax // so now your SQL Command is all built with parameters and ready to go. return SqlDataTable( cmd ); } 

我的build议:使用orm。 从现在开始有很多select