C# 防止动态代码中的sql注入

C# 防止动态代码中的sql注入,c#,sql-server,sql-injection,C#,Sql Server,Sql Injection,我需要从C代码执行带有sql查询的动态字符串,并防止sql注入 我的代码是这样的: internal static string Get_Running_Cars(string from, string to) { return string.Format( " declare @from as datetime = '{0}'" + " declare @to as datetime =

我需要从C代码执行带有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
                 );
        }
在该代码中,我可以在这些字符串中插入恶意代码

我怎样才能安全地使用它?
我应该防止这些字符:',;,-

如果您愿意,可以称之为新手方法,但如何尝试事先将输入解析为DateTime格式


正确、更简单、更快和更安全的方法是使用参数化查询。假设使用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执行该命令

使用,它更容易。一条线将通过以下参数:

 IEnumerable<Car> cars=connection.Query<Car>(sql,new {From=@from, To=@to});
这将在内部创建一个SqlCommand,传递参数,执行查询并将结果映射到cars

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

如果不是这些方法之一,则必须指定使用的数据访问方法

在实体框架中,您可以使用LINQ获取此查询,使用计算日期差:

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
                     }

我使用EF,因此最好的答案是使用'SqlParameter'

我构建这个对象:

public class SqlQueryEntity
    {
        public string query { get; set; }
        public object[] _params { get; set; }
    } 
并将其与DbRawSqlQuery一起发送

我需要插入带有“object”数组的查询,该数组包含:

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

“to”和“from”可以包含Datetime对象。

很容易将此代码移动到存储过程中,通过传递参数可以轻松防止sql注入。使用动态查询有什么具体要求吗?这里绝对没有理由使用动态查询。我需要注入100多个查询,因此我需要使用动态查询。我不能接受100个查询并将它们全部转换为存储过程。有没有一种好方法可以插入这些查询?您不必使用存储过程,但应该使用适当的参数,而不是将它们的字符串表示形式连接到查询的文本中。没有。只需使用参数化查询。使用ADO.NET,所需的行数大致相同。有了Dapper,就两个首先,这应该是一个评论。其次,如果您创建了一个DateTime,为什么不做正确的事情并使用适当的参数化查询呢?这里绝对没有理由使用字符串连接。此函数是150个函数之一。在这种情况下,您有datetime,在另一种情况下,您有不同的对象。我无法验证所有这些。这不是一个好答案,但是谢谢anyway@EliadAyehu不要传递字符串。只需使用参数化查询并传递强类型值。实际上,将DateTime参数传递给查询所需的代码比问题或答案少。如何执行查询?ADO.NET?EF?矮小利落的使用Dapper,您总共可以使用2行,其中一行用于string@PanagiotisKanavos是的,我正在尝试转换为DateTime,只是为了检查它是否不是注入。我意识到我也可以使用创建的日期时间。遗憾的是,我对mysql不是很有经验。就我个人而言,我什么都不知道。你没抓住重点。您不需要传递或转换任何内容。如果使用SqlCommand,则可以将@from和@to视为参数,并将日期时间值传递给它。无需在EF中为此查询编写SQL,只需使用适当的Where、Select和Take3语句即可。为了获得所需的日期差,如果要使用函数,它将嗅探参数的类型,并生成executeatetime from、DateTime To方法。做错事是不可能的!
new SqlParameter[] { 
                    new SqlParameter("from", from),
                    new SqlParameter("to", to)
                }