SQL 参数化与使用 string.format
SQL Parameterization versus using string.format
在防御SQL注入方面,对于更简单的查询,以下策略是否比另一种更有效?:
使用参数化:
using (SqlCommand command = new SqlCommand(@"SELECT * FROM @table", connection))
{
command.Parameters.AddWithValue("@table", table_name);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
...
}
}
}
使用string.Format
:
using (SqlCommand command = new SqlCommand(string.Format(@"SELECT * FROM {0}",table_name), connection))
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
...
}
}
始终使用参数化查询,使 sql 计划只有一个实例(只是为了获得最佳性能)。
参数化查询看起来像那个
select * from Table t where t.Id = @P1
参数化在 SQL 注入方面更安全。它也更适合处理字符串和日期。例如,如果您的字符串是这样的:
"I haven't sleep in two days"
如果您尝试在查询中 String.Format 它,则必须将 ' 字符加倍,否则您的查询将失败。就好像你对它进行参数化一样,SQL 会自动完成。
我做 String.Format 的唯一原因是当我有一个 int 列表并想做一个 "WHERE COL IN () " 条件时。在这种情况下,我将执行 String.Format 并加入 int 上的列表以生成 "IN" 子句内的值。请注意,在那种情况下,我有一个 int 列表,所以这里没有 SQL 注入的机会。
有时我总是将 String.Format 用于动态 SQL,例如指定 table 的名称,就像您的示例一样。
我在评论中稍微提到了这一点,但我也会 post 在这里回答。
参数化(在我看来)总是要走的路,因为它确保了查询的 "security"(注入到参数化查询中的 harder/impossible),并且还允许查询计划的重用,这也有很大的好处。
但是,对于您所拥有的,您无法按预期对 SQL 进行参数化。变量不能替换对象的名称 (db<>fiddle)。为此,您需要动态 SQL。
我不会假装我知道 C#,但是,对于你所拥有的,这意味着你有一个类似于 "something" 的查询,例如:
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#,但这就是您用(非常)简单的术语对动态对象进行参数化的方式。
在防御SQL注入方面,对于更简单的查询,以下策略是否比另一种更有效?:
使用参数化:
using (SqlCommand command = new SqlCommand(@"SELECT * FROM @table", connection)) { command.Parameters.AddWithValue("@table", table_name); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { ... } } }
使用
string.Format
:using (SqlCommand command = new SqlCommand(string.Format(@"SELECT * FROM {0}",table_name), connection)) using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { ... } }
始终使用参数化查询,使 sql 计划只有一个实例(只是为了获得最佳性能)。
参数化查询看起来像那个
select * from Table t where t.Id = @P1
参数化在 SQL 注入方面更安全。它也更适合处理字符串和日期。例如,如果您的字符串是这样的:
"I haven't sleep in two days"
如果您尝试在查询中 String.Format 它,则必须将 ' 字符加倍,否则您的查询将失败。就好像你对它进行参数化一样,SQL 会自动完成。
我做 String.Format 的唯一原因是当我有一个 int 列表并想做一个 "WHERE COL IN () " 条件时。在这种情况下,我将执行 String.Format 并加入 int 上的列表以生成 "IN" 子句内的值。请注意,在那种情况下,我有一个 int 列表,所以这里没有 SQL 注入的机会。
有时我总是将 String.Format 用于动态 SQL,例如指定 table 的名称,就像您的示例一样。
我在评论中稍微提到了这一点,但我也会 post 在这里回答。
参数化(在我看来)总是要走的路,因为它确保了查询的 "security"(注入到参数化查询中的 harder/impossible),并且还允许查询计划的重用,这也有很大的好处。
但是,对于您所拥有的,您无法按预期对 SQL 进行参数化。变量不能替换对象的名称 (db<>fiddle)。为此,您需要动态 SQL。
我不会假装我知道 C#,但是,对于你所拥有的,这意味着你有一个类似于 "something" 的查询,例如:
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#,但这就是您用(非常)简单的术语对动态对象进行参数化的方式。