【问题标题】:Does stored procedure help eliminates SQL injection / What are the benefits of stored procedured over normal SQL statement in apps?存储过程是否有助于消除 SQL 注入/与应用程序中的普通 SQL 语句相比,存储过程有什么好处?
【发布时间】:2009-07-23 19:39:44
【问题描述】:

我对 SQL 世界很陌生。以下是我的问题:

  • 与应用程序中的普通 SQL 语句相比,存储过程有哪些优势?
  • 存储过程是否有助于消除 SQL 注入?
  • 在 Microsoft SQL Server 中,它被称为存储过程。在 Oracle、MySQL、DB2 等中怎么样?

感谢您的解释。

【问题讨论】:

    标签: sql database stored-procedures


    【解决方案1】:

    如果您以参数化方式调用存储过程,则仅直接防止 SQL 注入。如果您的应用程序中仍有一个字符串,其中包含过程名称并将用户输入的参数连接到代码中的该字符串,那么您仍然会遇到麻烦。

    但是,当单独使用时,存储过程允许您通过禁用除 EXEC 命令之外的所有内容的权限来添加一些额外的保护。除此之外,参数化查询/准备语句通常由服务器缓存,因此几乎在各个方面都像存储过程。

    尽管如此,存储过程对于大型企业来说有两大优势:

    • 它们允许您为数据库定义应用程序接口,以便系统可以在多个应用程序之间共享,而无需在这些应用程序中复制逻辑。
    • 他们将 sql 代码移动到 db,在那里您可以轻松地让有经验的 DBA 调整、更新和维护它,而不是经常不知道他们正在使用数据库代码做什么的应用程序开发人员。

    当然,这些优势并非没有代价:

    • 很难跟踪源代码管理中的更改
    • 数据库代码与使用它的代码相距甚远
    • 用于管理许多存储过程的开发人员工具并不理想(如果您曾经在 Management Studio 中打开存储过程文件夹以查找 200 个数据库过程,那么您知道我在说什么)。

    【讨论】:

    • 虽然您的优势在有 DBA 员工的中型/大型企业中可能是真实的,但对于像我这样以清理其他人的代码为生的人来说,这是一场噩梦。性能优势根本不值得在小企业中冒被滥用的风险。
    【解决方案2】:

    我在使用存储过程时考虑到的一些好处

    • 存储过程将查询代码封装在服务器上,而不是在应用程序内部。这允许您更改查询,而无需重新编译您的应用程序。
    • 存储过程可用于更明确定义的应用程序安全性。您可以拒绝对基表的所有权限,仅在 procs 上授予执行权限。这让您需要管理的安全足迹要小得多。
    • 存储过程是编译代码。使用最新版本的 MSSQL,服务器可以更好地存储执行计划 - 所以这不再像以前那样大,但仍然需要考虑
    • 存储过程只有在正确使用时才能消除 SQL 注入风险。确保在存储过程中以正确的方式使用参数 - 仅在其中执行串联动态 SQL 的存储过程对任何人都没有任何好处。

    【讨论】:

    • 我不同意 Bouma 的观点。 ORM 在软件开发中占有一席之地,存储过程也是如此。完全写下一个或另一个似乎是一个不好的立场。最初的发帖人说他是“SQL 新手”——因此他应该尽可能地学习有关存储过程和 orm 的所有知识——这样他就可以为他所从事的每个项目做出明智的决定,以确定哪个项目适合当前情况.
    • Re: sprocs are bad article: RUBBISH 1) 所有 SQL 都很脆弱 - 不管它在哪里,模型更改都需要更新它(包括应用程序代码)2) 洋葱防御,其中安全性是分层的。 3) 性能 - 用您选择的语言向我展示一个执行速度比 FOR 循环慢的游标,我将向您展示一个急需调整的 SQL 语句。
    • @rexam - 说得好。说“坏立场”时,我不得不调整措辞……
    【解决方案3】:

    在大多数情况下是的,SQL 注入在存储过程中的可能性要小得多。尽管有时您想要传递存储过程的一些数据,这些数据需要您在存储过程中使用动态 SQL,然后您又回到了开始的位置。从这个意义上说,我认为它们与在支持它们的编程语言中使用参数化查询相比没有任何优势。

    我个人讨厌存储过程。将代码放在两个不连贯的地方是一件很痛苦的事情,它使部署变得更加复杂。我也不提倡在代码中乱扔 SQL 语句,因为这会导致它自己的一系列问题。

    我建议使用以下两种方式之一实现 DAL 层。

    1. 我的最爱,使用一个对象 关系管理系统(ORM)。 我一直在使用 nHibernate 我非常喜欢它。这 学习曲线陡峭但 绝对值得我的回报 意见。
    2. 某种保持机制 您所有的 SQL 代码都在一个地方。 某种查询库 你选择或真的 结构化的类集 为您设计 SQL。我不 推荐这种方式,因为它是 基本上就像构建自己的 ORM 很可能你没有时间 正确地做到这一点。

    忘记存储过程。使用 ORM。

    【讨论】:

    • 或者更好 - 使用使用存储过程的 ORM。
    • @Scott:不知道存在,但是是的,这也是一个不错的选择。
    【解决方案4】:

    存储过程(不使用动态 SQL 的)可以使整个应用程序更加安全的一种方法是,您现在可以在存储过程级别而不是表级别设置权限。如果您以这种方式进行所有数据访问(并禁止动态 sql!),这意味着用户在任何情况下都不能对不在存储过程中的数据库做任何事情。开发人员总是想说他们的应用程序代码可以抵御外部威胁,但他们似乎忘记了内部威胁通常要严重得多,并且通过允许表级别的权限,他们任由任何能找到方法的用户摆布直接在应用程序外部查询数据库(另一个原因是大商店最多只有两三个人对数据库中的任何内容有生产权限,这限制了谁可以窃取信息)。

    例如,使用除存储过程之外的任何东西的任何财务系统都完全容易发生内部欺诈,这违反了应防止欺诈的内部控制,并且不会通过良好的审计。

    【讨论】:

      【解决方案5】:

      存储过程允许您将 sql 代码存储在应用程序之外的位置。这使您能够:

      • 更改 SQL 代码而不重新编译/重新分发应用程序
      • 让多个应用程序使用相同的存储过程来访问相同的数据。
      • 限制用户直接读取/写入数据库中的表。
      • 从开发的角度来看,它还允许 DBA/数据库程序员处理 sql 代码,而无需通过应用程序代码来处理它。 (本质上是职责分离)。

      存储过程可以防止注入攻击吗?多半是对的。在 sql server 中,您可以创建对此无效的存储过程,主要是使用 sp_executesql。现在这并不是说 sp_executesql 是一个安全漏洞,它只是意味着在使用它时需要采取更多的预防措施。

      这也不意味着存储过程是防止这种情况的唯一方法。您可以使用参数化 sql 来完成防止 sql 注入的相同任务。

      我确实同意其他人的看法,存储过程可能很麻烦,但它们也有其优点。在我工作的地方,由于各种原因(不要问),我们可能有 20 个不同的生产数据库。我的工作可能只有三个,我和我的队友非常了解这三个。存储过程如何帮助我们?人们来找我们,当他们需要从这些数据库中获取信息时,我们可以为他们获取信息。我们不必花费数小时来解释模式和非规范化的数据。这是一个抽象层,它允许我们针对我们知道的数据库编写最有效的代码。如果您不是这种情况,那么存储过程可能不是可行的方法,但在某些情况下它们可以增加很多价值。

      【讨论】:

      • 在不重新编译/重新分发应用程序的情况下更改 SQL 代码。!?当然需要编译。仅仅因为您不调用 make 或 ant 或其他什么,并不意味着它没有被编译。更重要的是:当然必须部署它,还是建议直接在生产数据库中更改代码?
      • 不,你是对的,我的意思是重新编译应用程序代码(如 C# 或 Java)。在某些情况下,您确实必须部署它,但在紧要关头,您可以从服务器中提取 sql 代码更新它并在必要时执行它,而不是像桌面应用程序那样您必须重新部署到可能的数百台机器上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      • 2013-06-22
      • 1970-01-01
      相关资源
      最近更新 更多