【问题标题】:SQL Variables as Column names in Where Clause [duplicate]SQL 变量作为 Where 子句中的列名 [重复]
【发布时间】:2013-08-21 14:25:03
【问题描述】:

我需要一些关于我的 SQL 逻辑的帮助,并且我已经工作(和研究)了 2 天,但成功率为零。

我的目标是尝试将变量从 ASP 页面传递到存储过程,该存储过程利用该变量作为 where 子句中列名的条件。

例如(我的查询的简化版本):

@strDept nvarchar(10), @strUser nvarchar(30)
-- The asp page will pass f18 to @strDept & Ted Lee to strUser
-- f18 is the column name in my database that I need in the where.

select x, y, z from table1 where @strDept in (@strUser)
-- and this is the select statement, notice the where clause.

存储过程确实执行了,但它不返回任何值,我知道它将 @strDept 视为文字 nvarchar 而不是列名。

所以我想我的问题是,如何让 SQL Server 2005 将我的 @sqlDept 变量视为列名?

【问题讨论】:

  • 所以@strUser 是一个以逗号分隔的整数列表?
  • 不,@struser 正在引用一个带有字符串的文本框,该文本框正在传递给存储的生产者。

标签: sql sql-server tsql


【解决方案1】:

您找不到有关如何执行此操作的指导的原因是,这是一个非常糟糕的主意

迟早会有人传递1 ;drop database badidea 的“列名”。这将是所有相关人员的祝福。

阅读 SQL 注入,重新思考您的设计。

【讨论】:

  • 是的,关于动态 SQL 的每条途径都让我走上了一条单向 SQL 注入的道路。但事情是这样的,用户不能显式地向存储过程传递任何东西——即使页面单独传递变量,这仍然容易受到注入攻击吗?
  • 如果参数被严格控制,那么没有。但这就是发生的事情。你部署它。然后迟早有人说“我们可以选择任何我们喜欢的领域吗?”,而你不在,有人说“哦,这看起来像一个简单的改变。我会稍微调整一下......
  • @SyD 还有,你说的是No, @struser is referencing a textbox with a string in it
  • 我听到你在说什么,这里有人(我的非编程经理)在我不在的情况下以不同的方式做到了这一点。它确实把事情搞砸了,但这对我来说是一个简单的解决方案,但是公司在我离开的 1 小时内一直处于停滞状态。
【解决方案2】:

如果这是一个公司内部应用程序,为什么每个人都在重复迭代并将 SQL 注入打死……使用动态 SQL 非常简单。 如果您对这些只是使用它的内部用户感到满意,那么它非常简单。这是概念。本质上,您编写了一个 SQL 语句,该语句编写一个实际上是 SQL 语句的字符串,然后执行它。

CREATE Procedure myDynamicProcedure
@strDept nvarchar(10), 
@strUser nvarchar(30)

as 

BEGIN

1.声明一个变量来存储 SQL 语句。

 DECLARE @SQL varchar(max)

2。将您的 @SQL 变量设置为 SELECT 语句。基本上你正在构建它,所以它返回你想要写的内容。像这样:

   SET @SQL = 'select x, y, z from table1 where' + @strDept + 
 ' in ' + @strUser

3.执行@SQL 语句,它会和你运行的一模一样: SELECT x,y,z from table1 where f18 = 'Ted Lee'

EXEC (@SQL)
END

【讨论】:

  • 用户只是点击一个链接,页面被写入显示他们需要的内容。注入部分由我的代码完成,这也是我考虑动态过程的原因。顺便说一句 - 谢谢,这看起来和我想写的完全一样。
  • @SyD - 没问题先生......有些答案有些令人困惑。当然,如果您需要这个面向公众的网站,我会 100% 同意所有注射安全功能。祝你好运!
【解决方案3】:

为什么要使列名动态化?你打算达到什么目标?您可以使用类似上述答案的动态查询,但可能会启动注入攻击。

如果你解释你想用它做什么,也许我们可以推荐另一种解决方案。

【讨论】:

  • 基本上,我的公司需要一个报告仪表板。仪表板将具有经理视图和个人视图。本质上是管道,但问题是数据库对部门有不同的字段,而这些字段具有各个员工的姓名。最简单的解决方案是只向过程传递一个数字,然后复制并粘贴一堆具有正确字段的 IF 语句,但这既费时又麻烦。我想根据部门asp页面动态输入列引用。
【解决方案4】:

您可以使用一些动态 sql,例如

DECLARE @sqlDept VARCHAR(100)='CURRENT_TIMESTAMP';

EXEC('SELECT '+@sqlDept)

在你的情况下,这将是

DECLARE @strDept nvarchar(10)='dept1'
,@strUser nvarchar(30)='user1';

DECLARE @DynamicSql nvarchar(1000);

SET @DynamicSql='select x, y, z from table where '+@strDept+' in ('''+@strUser+''')';

然后

SELECT @DynamicSql;

会给你:

从 ('user1') 中的 dept1 表中选择 x、y、z

要执行这个语句,你可以这样做

EXEC(@DynamicSql);

【讨论】:

  • 我不确定我是否理解上面的代码在做什么 - 你能解释一下吗?
  • 我同意其他 cmets 关于注射的看法,但我已将答案更新为更清晰一些。
【解决方案5】:

另一种选择是在 proc 中使用少量替换。这仍然使用动态 SQL,但您永远不会执行用户提供的值。

DECLARE @userSuppliedValue VARCHAR(50) = 'JOHNNY DROP TABLES'


DECLARE @substValue VARCHAR(50)

IF @userSuppliedValue = 'Table1'
  SET @substValue = 'Table1'

IF @userSuppliedValue = 'Table2'
  SET @substValue = 'Table2'

/*Repeat for N permutations*/

/* Throw an error if you think its necessary to do so when no match is found*/
IF @substValue IS NULL
  RAISERROR(1,1,'errah')

EXEC ('SELECT * FROM ' + @substValue)

【讨论】:

  • 非常有趣的方法,谢谢。 :)
【解决方案6】:

我认为最好的方法是构建动态SQL并添加查找以查看列是否存在并防止列名中的SQL注入。

declare @strDept nvarchar(10), @strUser nvarchar(30), 
        @sql nvarchar(300), @found smallint
set @strDept = 'f18'
set @strUser = 'Ted Lee'

set @found = (SELECT count(*) 
              FROM syscolumns 
              WHERE id=OBJECT_ID('table1') AND name=''+@strDept+'')

set @sql = 'select x, y, z from table1 where ' + @strDept + ' in ('''+@strUser+''')'

if @found = 1 exec (@sql)

SQL 注入测试:参见 SQL FIDDLE:http://www.sqlfiddle.com/#!6/df3f6/18/0

【讨论】:

  • 除非他们疯狂到使用名为 [1;删除表用户]
【解决方案7】:
DECLARE @value varchar(10)  
SET @value = 'intStep'  
DECLARE @sqlText nvarchar(1000); 

SET @sqlText = N'SELECT ' + @value + ' FROM dbo.tblBatchDetail'
Exec (@sqlText)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    相关资源
    最近更新 更多