FromSql():从字符串列表中查询字符串构建以防止注入

时间:2019-04-15 17:27:43

标签: c# sql-server .net-core entity-framework-core sql-injection

我正在EF Core中构建SQL搜索。 Microsoft建议您不要连接字符串,因为它会使应用程序容易受到SQL注入的影响,如Microsoft文档:https://docs.microsoft.com/en-us/ef/core/querying/raw-sql中所述。

  

对于原始SQL查询始终使用参数化:   验证用户输入,请始终对使用的任何值使用参数化   在原始SQL查询/命令中。接受原始SQL字符串的API,例如   FromSql和ExecuteSqlCommand允许将值轻松传递为   参数。接受的FromSql和ExecuteSqlCommand的重载   FormattableString还允许在字符串中使用字符串插值语法   防止SQL注入攻击的方法。

     

如果您使用字符串串联或插值来动态   构建查询字符串的任何部分,或将用户输入传递给   可以执行以下输入的语句或存储过程:   动态SQL,则您负责验证对   防止SQL注入攻击。

此数据库中存储的信息不敏感,但是显然我不想让数据库容易受到攻击。

我有一个参数List<string> searchTerms,我需要对其进行遍历并基于此列表构建查询。

我将把字符串和SQL查询一起使用,但是我只能看到如何通过串联来做到这一点。现在我的代码看起来像这样。

var query = String.Format("SELECT ... where MySqlField like '%{0}%'", searchTerm[0]);

for (int i = 1; i < searchTerm.Count(); i++)
{
    query += String.Format(" and MySqlField like '%{0}%'", searchTerm[i]);
}

var results = context.MySqlTable.FromSql(query);

即使我使用的是插值法,在这里进行额外的验证就足够了吗?我想念什么吗?

是否存在可以使用列表执行相同操作的linq查询?

4 个答案:

答案 0 :(得分:1)

我目前无法对其进行测试,所以我让您了解这种方法

List<string> ph = new List<string>();
int count = 0;
foreach(string s in searchTerm)
{
    ph.Add($"MySqlField LIKE '%{{{count}}}%'");
    count++;
}

if(count > 0)
    query = query + " WHERE " + string.Join(" OR ", ph);
var results = context.MySqlTable.FromSql(query, searchTerm.ToArray());

虽然它看起来像是字符串连接方法,但我们可以阅读docs

  

虽然看起来像String.Format语法,但是提供的值是   包装在参数中,并将生成的参数名称插入到   指定了{0}占位符。

答案 1 :(得分:1)

选项很少:

  1. 以XML(如果使用更新的SQL Server,则为JSON)传递值,然后编写静态XML / JSON查询。

  2. 创建一个临时表,将所有搜索值插入到临时表中,然后执行静态查询。

答案 2 :(得分:0)

您的代码经过一些修改后应该足够好了

var query = String.Format("SELECT ... where 1=1 ");

for (int i = 0; i < searchTerm.Count(); i++)
{

    query += $" and MySqlField like '%'+{{{i}}}+'%'";
}

var results = context.MySqlTable.FromSql(query, searchTerm.ToArray());

答案 3 :(得分:-1)

如果您使用EF,我建议您调查LINQ。对于安全性和性能而言,使用原始字符串sql并不是一个好主意。 LINQ提供了一种执行查询的可靠方法。只是要小心如何编写查询,因为LINQ可能会过度尝试使查询变得过于复杂。

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/

编辑:

我错过了您帖子的最后一行。抱歉,以下内容应有助于您走上正确的路:

for (var item in searchTerms) {
    query = query.Where(w => w.MySqlField.Contains(item.Value));
}