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

FromSql(): Query string building from string list to prevent injection

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

Always use parameterization for raw SQL queries: In addition to validating user input, always use parameterization for any values used in a raw SQL query/command. APIs that accept a raw SQL string such as FromSql and ExecuteSqlCommand allow values to be easily passed as parameters. Overloads of FromSql and ExecuteSqlCommand that accept FormattableString also allow using string interpolation syntaxt in a way that helps protect against SQL injection attacks.

If you are using string concatenation or interpolation to dynamically build any part of the query string, or passing user input to statements or stored procedures that can execute those inputs as dynamic SQL, then you are responsible for validating any input to protect against SQL injection attacks.

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

我有一个参数 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 查询?

如果您使用的是 EF,我建议您研究一下 LINQ。使用原始字符串 sql 对于安全性和性能来说都不是一个好主意。 LINQ 提供了一种执行查询的可靠方法。请注意您如何编写查询,因为 LINQ 可能会过度尝试使它们过于复杂。

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

编辑:

我错过了你的最后一行 post。抱歉,以下内容应该可以帮助您走上正轨:

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

我暂时无法测试,所以我告诉你这个方法

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

While this may look like String.Format syntax, the supplied value is wrapped in a parameter and the generated parameter name inserted where the {0} placeholder was specified.

选项很少:

  1. 在XML(或JSON,如果使用较新的SQL服务器)传递你的值,然后写静态XML/JSON查询。

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

您的代码稍加修改就可以了:

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());