2016-09-21 97 views
-1

我需要从C#代码执行动态字符串与SQL查询并防止SQL注入。防止动态代码中的SQL注入

我的代码是这样的:

internal static string Get_Running_Cars(string from, string to) 
     { 
      return string.Format(
       " declare @from as datetime = '{0}'" + 
       " declare @to as datetime = '{1}'" + 
       " select top 3 DATEDIFF(second,starttime,endtime) as sum,carname as name" + 
       " from cars" + 
       " where @from < starttime and @to > endtime ", from, to 
       ); 
     } 

的代码,我可以恶意代码插入到这些字符串。

我该如何安全使用它? 我应该防止那些字符:',;,,-

+0

将此代码移至存储过程非常容易,您可以通过传递参数轻松防止sql注入。有什么具体的要求使用动态查询? –

+4

这里绝对没有理由使用动态查询。 – Maarten

+0

我有超过100个需要注入的查询,因此我需要使用动态查询。 我不能接受100个查询并将其全部转换为存储过程。 是否有注入这些查询的好方法? –

回答

1

我用EF,因此,最好的答案是使用“的SqlParameter”。

我建立这个对象:

public class SqlQueryEntity 
    { 
     public string query { get; set; } 
     public object[] _params { get; set; } 
    } 

与DbRawSqlQuery发送。

我需要与“对象”包含的阵列插入查询:

new SqlParameter[] { 
        new SqlParameter("from", from), 
        new SqlParameter("to", to) 
       } 

“到”和“从”能够包含DateTime对象。

1

如果您愿意,可以将其称为菜鸟方法,但如何尝试事先将输入解析为DateTime格式?

DateTime.TryParse()

internal static string Get_Running_Cars(string from, string to) 
    { 
     DateTime test1, test2; 
     if (!DateTime.TryParse(from, out test1) || !DateTime.TryParse(to, out test2)) 
      return null; 
     //else is optional here, to show logic 
     return string.Format(
      " declare @from as datetime = '{0}'" + 
      " declare @to as datetime = '{1}'" + 
      " select top 3 DATEDIFF(second,starttime,endtime) as sum,carname as name" + 
      " from cars" + 
      " where @from < starttime and @to > endtime ", from, to 
      ); 
    } 
+1

首先,这应该是一个评论。其次,如果您创建DateTime,为什么不做正确的事情并使用适当的参数化查询?这里绝对没有理由使用字符串连接。 –

+0

此功能是150个功能之一。在这种情况下,你有日期时间,在其他情况下,你有不同的对象。我无法验证所有这些。这不是一个好的答案,但无论如何感谢 –

+1

@EliadAyehu - 这不是一个好问题要么 –

2

正确的,更容易,更快更安全的方法是使用参数化查询。假设你使用ADO.NET,您可以使用下面的方法来创建一个参数化查询:

public SqlCommand BuildCarsCommand(DateTime from,DateTime to) 
{ 
    var sql= "select top 3 DATEDIFF(second,starttime,endtime) as sum,carname as name" + 
     " from cars where @from < starttime and @to > endtime "; 
    var cmd=new SqlCommand(sql); 
    cmd.Paramerers.AddWithValue("@from",from); 
    cmd.Parameters.AddWithValue("@to", to); 

    return cmd; 
} 

您可以SqlCommand.ExecuteReader

使用Dapper执行命令,那就更简单了。单行将通过参数:

IEnumerable<Car> cars=connection.Query<Car>(sql,new {[email protected], [email protected]}); 

这将在内部创建一个SqlCommand,传递参数,执行查询,并将结果向汽车映射。

实体框架和大多数ORM允许您运行参数化查询。

如果不是其中之一,则必须指定使用哪种数据访问方法。

在实体框架,你可以使用LINQ这样的语句,使用SqlFunctions.DateDiff来计算日期差:

var cars=from car in myDbContext.Cars 
     where car.starttime > from and car.endtime < to 
     select new { 
         sum=SqlFunction.DateDiff("second", car.starttime,car.endtime), 
         name=carname 
        } 
+0

看起来不错,但我如何使用它与EF? –

+0

您不需要在EF中为此查询编写SQL,只需使用适当的Where,Select和Take(3)语句即可。要获取日期差异,您需要[SqlFunctions.DateDiff](https://msdn.microsoft.com/en-us/library/dd487052(v = vs.110).aspx)函数 –

+0

如果您使用[QueryFirst] (https://visualstudiogallery.msdn.microsoft.com/eaf390af-afc1-4994-a442-ec95923dafcb),它会嗅探参数的类型并生成方法Execute(DateTime from,DateTime to)。这是不可能做错的! – bbsimonbb