【问题标题】:Alternatives to using dynamic sql使用动态 sql 的替代方法
【发布时间】:2012-08-21 15:22:07
【问题描述】:

我有一个接受输入 @featuretype 的 sp。 @featuretype 将等于“mobile”、“login”或“index”,并将对应于 db 中的列。

在我的 sp 我有:

EXEC(
    'select TOP 3 * from featuredtypes_v where'+' featuredtypes_v.'+@featuretype+'Page=1'+
    ' order by featuredtypes_v.priority desc'
    )

但是,有人告诉我这会打开数据库进行 sql 注入。我的两个问题是,为什么会这样,为了避免这种情况,我还能如何编写这个查询?

【问题讨论】:

  • 想象@featuretype;drop table featuredtypes_v; --
  • 很好地处理了这个问题,而不仅仅是把它扫到地毯下!

标签: sql tsql stored-procedures


【解决方案1】:

你为什么不用case

select TOP 3 * 
from featuredtypes_v F
where
    case
        when @featuretype = 'mobile' then F.MobilePage
        when @featuretype = 'login' then F.LoginPage
        when @featuretype = 'index' then F.IndexPage
    end
    = 1

【讨论】:

  • +1 - 我一直在努力做到这一点,但被转移了。干净整洁
【解决方案2】:

如果用户提供传递给变量的值,或者如果有人找到一种方法来执行存储过程并传入特制的恶意代码,则您的过程可能会被注入。谷歌我的用户名,以获取基于此的有趣漫画。

由于您处于存储过程中,因此您可以检查变量,然后根据提供的变量执行 SELECT 语句:

IF @featuretype = 'mobile'
BEGIN
    select TOP 3 * 
    from featuredtypes_v 
    where featuredtypes_v.MobilePage=1
    order by featuredtypes_v.priority desc
END
IF @featuretype = 'login'
BEGIN
    select TOP 3 * 
    from featuredtypes_v 
    where featuredtypes_v.LoginPage=1
    order by featuredtypes_v.priority desc
END
-- etc...

或者,您可以将条件放在 WHERE 子句中的一个查询中:

select TOP 3 * 
from featuredtypes_v 
where (featuredtypes_v.MobilePage=1 AND @featuretype = 'Mobile') OR 
    (featuredtypes_v.LoginPage=1 AND @featuretype = 'Login') OR
    (featuredtypes_v.IndexPage=1 AND @featuretype = 'Index')
order by featuredtypes_v.priority desc

【讨论】:

  • 这种方法的缺点是它不重用查询执行计划,因为执行可能会因参数而异。这会影响执行,但比使用动态 sql 更安全。
  • @Nathan - 是的,事后看来,我对这个答案并不满意,尽管我会把它作为参考。它们有效,但有更好、更明显的解决方案,我不确定自己在想什么。
【解决方案3】:

一种方法是这样。确保该列存在于表中,然后执行动态sql,否则不存在。

if Exists(select * from sys.columns where Name = N'@featuretype'  
            and Object_ID = Object_ID(N'tableName'))
begin

   EXEC(
    'select TOP 3 * from featuredtypes_v where'+' featuredtypes_v.'+@featuretype+'Page=1'+
    ' order by featuredtypes_v.priority desc'
    )

end

【讨论】:

    【解决方案4】:

    你们都没有回答问题。 这是 sql 注入可能发生的事情

    txtUserId = getRequestString("UserId");
    txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
    

    现在如果 txtUser = 105 OR 1=1 那么 sql 语句将是这样的

    SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;
    

    您可以通过使用 sql 参数来避免 sql 注入。它验证字符串和 sql 执行 alwaus 就像它假设的那样

    【讨论】:

      猜你喜欢
      • 2017-06-28
      • 1970-01-01
      • 2016-04-19
      • 2014-10-22
      • 2019-11-09
      • 2023-02-03
      • 2022-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多