Csharp/C#教程:在C#中使用动态SQL的变量表名分享


在C#中使用动态SQL的变量表名

我一直在寻找一种输入变量表名的方法,看起来最好的方法是使用动态sql,虽然它可以导致SQL注入。 谁能certificate这是如何在C#中完成的? 例如,我想要实现这样的东西:

SqlCommand command= new SqlCommand("SELECT x FROM @table WHERE @column = @y", conn); 

从中可以看出,表名和列名将是变量。 我之前使用的是字符串连接,但为了安全起见,我想避免这种情况。 不确定它是否重要,但表和列不是由用户输入决定的,而是由用户选择的链接确定,所以也许SQL注入不是问题吗?

我能想到的最佳方式是两部分。

  1. 您有一个存储过程,将名称作为参数。 这个proc首先查找目录中的表名( Information_Schema.Table )并获取正确的名称以validation它是否有效。

  2. 然后使用此查找,存储过程构造所需的SQL,而不是参数。

使用此查找,您基本上可以防止传入非有效的表名。

 CREATE PROCEDURE RunSQL (@table NVARCHAR(50)) AS BEGIN DECLARE @validTableName NVARCHAR(50) SELECT @validTableName = TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @table AND SCHEMA_NAME = 'dbo' -- here you can limit or customise the schema IF @validTableName IS NULL RAISE ... raise an exception DECLARE @dynamicSql NVARCHAR(100) = REPLACE('SELECT * FROM dbo.[#TABLE#]', '#TABLE' @validTableName) EXECUTE sp_executesql .... @dynamicSql .... END 

你可以使用extend this来validation,模式,列等……

您最终需要构建自己的SQL并执行注入保护。 没有绕过那个。

您似乎必须使用动态SQL,这基本上意味着您必须将表名串联到查询字符串中并通过TSQL中的“sp_executesql”存储过程运行它。

使用SqlCommand不是动态SQL。 虽然您正在动态构建SQL字符串,但您仍然在运行一个普通的旧SQL字符串。

为了安全地执行此操作并针对SQL注入进行投影,您必须确保表名有效,并且必须通过任何必要的方法自行完成。 幸运的是,你有3个不错的选择,其中一个很容易,几乎是万无一失的。

正如其他人所说,你可以:

  1. 根据白名单检查名称,或
  2. 在系统表中查找名称以查看它是否是真正的表名,或者
  3. 只需使用QUOTENAME函数来转义字符并使它们成为带引号的标识符。

我有一个关于按名称删除表的类似问题,这就是提到QUOTENAME函数的地方: https : //stackoverflow.com/a/19528324/88409

要使用动态SQL,您实际上必须执行以下操作:

 string sql = "declare @query nvarchar(max) = 'SELECT * FROM ' + QUOTENAME(@tablename) + ' WHERE ' + QUOTENAME(@columnname) + ' = @cv'; " + "declare @params nvarchar(500) = N'@cv nvarchar(500)'; " + "exec sp_executesql @query, @params, @cv=@columnvalue;"; SqlCommand command = new SqlCommand( sql, conn ); command.Parameters.AddWithValue( "@tablename", tableName ); command.Parameters.AddWithValue( "@columnname", columnName ); command.Parameters.AddWithValue( "@columnvalue", columnValue ); 

如果SqlCommand类很可能不支持带有’declare’语句的复杂查询,那么你需要将’sql’字符串的值移动到一个存储过程中,该存储过程接受相同的三个参数然后调用它通过将SqlCommand.CommandType设置为StoredProcedure来命名,如下所示:

 SqlCommand command = new SqlCommand( "MyStoredProcedureName", conn ); command.CommandType = System.Data.CommandType.StoredProcedure; command.Parameters.AddWithValue( "@tablename", tableName ); command.Parameters.AddWithValue( "@columnname", columnName ); command.Parameters.AddWithValue( "@columnvalue", columnValue ); 

最简单的方法是简单地使用字符串连接将表名放入SQL查询中。 但是,只要恶意用户可以向查询中注入任意字符串,您仍然可以使用SQL注入。 例如,假设您的APIurl是https://example.org/all?table_name=customer&order=desc ,而您只是从用户名的URL中提取“table_name”。

您应该通过具有有效表名称的静态服务器端白名单来阻止可能的SQL注入(例如String[] ValidTableNames = new String[] { "customer", "purchase", ... } ,并确保table_name参数值为将其添加到SQL查询之前的其中一个值。

我曾经创建了一个允许某些用户访问特定表的网站。 使用ASP成员资格和用户ID我有一个表,用于在创建用户帐户时建立USER ID之间的关系。 当时已分配了允许访问的表名。 表名是硬编码的,并根据项目的参数动态构建。 因此,tblCustomersNew或tlbInventoryOld等表链接到UserID。

当用户登录时,我只是针对SQL表查询UserID以获取表名,然后将其添加到查询中或将其传递给存储过程。

效果很好,所有这些都发生在经过身份validation的用户帐户后面。

编辑:我只想补充一点,这可以避免SQL注入,因为您的表名在项目中预定义并存储在数据库中。 您只需使用经过身份validation的用户帐户查询它们即可访问用户有权访问的表。

上述就是C#学习教程:在C#中使用动态SQL的变量表名分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/961025.html

(0)
上一篇 2021年11月25日
下一篇 2021年11月25日

精彩推荐