0

在防御 SQL 注入方面,对于更简单的查询,以下策略之一是否比另一个更有效?:

  1. 使用参数化:

    using (SqlCommand command = new SqlCommand(@"SELECT * FROM @table", connection))
    {
        command.Parameters.AddWithValue("@table", table_name);
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                ...
            }
        }
    }
    
  2. 使用string.Format

    using (SqlCommand command = new SqlCommand(string.Format(@"SELECT * FROM {0}",table_name), connection))
    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            ...
        }
    }
    
4

3 回答 3

2

我在评论中稍微提到了这一点,但我也会在这里发布答案。

参数化(在我看来)始终是要走的路,因为它确保了查询的“安全性”(注入参数化查询更加困难/不可能),并且还允许重用查询计划,这也可以是大有裨益。

但是,对于您在这里所拥有的,您无法按预期对 SQL 进行参数化。变量不能替换对象的名称(db<>fiddle)。为此,您需要动态 SQL。

我不会假装我知道 C#,但是,对于你所拥有的,我不会,这意味着你有一个类似于“某事”的查询,例如:

using (SqlCommand command = new SqlCommand(@"DECLARE @SQL nvarchar(MAX) = N'SELECT * FROM ' + QUOTENAME(@table) + N';'; EXEC sp_executesql @SQL;", connection))
{
    command.Parameters.AddWithValue("@table", table_name);

老实说,我不知道这是否在 C# 中以这种方式工作,但这将是您如何以(非常)简单的术语参数化动态对象。

于 2019-02-22T16:03:06.877 回答
1

就 SQL 注入而言,参数化更安全。处理字符串和日期也更好。例如,如果您的字符串是这样的:

"I haven't sleep in two days"

如果您尝试在查询中对其进行 String.Format ,则必须将 ' 字符加倍,否则您的查询将失败。就像你参数化它一样,SQL 会自己做。

我做 String.Format 的唯一原因是,例如,当我有一个 int 列表并想做一个“WHERE COL IN ()”条件时。在这种情况下,我将执行 String.Format 并在 int 上加入 List 以在“IN”子句中生成值。请注意,在这种情况下,我有一个 int 列表,因此这里没有 SQL 注入的机会。

我总是有时将 String.Format 用于动态 SQL,例如指定表的名称,就像在您的示例中一样。

于 2019-02-22T15:56:39.510 回答
0

始终使用参数化查询来只有一个 sql 计划实例(只是为了获得最佳性能)。

参数化查询看起来像那个

select * from Table t where t.Id = @P1
于 2019-02-22T15:55:53.560 回答