【问题标题】:Parameter Binding: What happens under the hood?参数绑定:幕后发生了什么?
【发布时间】:2010-09-06 02:36:11
【问题描述】:

.NET、Java 和其他各种语言的高级数据库 API 通常提供称为准备语句和参数绑定的技术,而不是向数据库服务器发送纯文本命令。我想知道的是当你执行这样的语句时会发生什么:

SqlCommand cmd = new SqlCommand("GetMemberByID");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("@ID", memberID);
para.DbType = DbType.Integer;
cmd.Parameters.Add(param);

我知道这是最佳做法。 SQL 注入攻击以这种方式被最小化。但是,当您执行这些语句时,幕后究竟发生了什么?最终结果仍然是 SQL 安全字符串吗?如果不是,最终结果是什么?这足以防止 SQL 注入攻击吗?

【问题讨论】:

    标签: c# .net sql database api


    【解决方案1】:

    The MySQL manual page 在prepared statements 上提供了大量信息(应该适用于任何其他RDBMS)。

    基本上,您的语句会被提前解析和处理,并且参数是单独发送的,而不是与 SQL 代码一起处理。这消除了 SQL 注入攻击,因为 SQL 在参数设置之前就已被解析。

    【讨论】:

      【解决方案2】:

      通俗地说:如果发送了一个准备好的语句,那么数据库将使用一个可用的计划,它不必在每次发送此查询时都重新创建一个计划,而只有参数的值有改变了。这与 procs 的工作方式非常相似,procs 的额外好处是您可以仅通过 procs 授予权限,而根本不能授予基础表

      【讨论】:

        【解决方案3】:

        如果您使用的是 MS SQL,请加载分析器,您将看到在使用参数化查询时生成了哪些 SQL 语句。下面是一个针对 SQL Server 2005 的示例(我使用的是 Enterprise Libary 3.1,但结果与直接使用 SqlParameters 相同):

        string sql = "SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did";
        Database db = DatabaseFactory.CreateDatabase();
        using(DbCommand cmd = db.GetSqlStringCommand(sql))
        {
          db.AddInParameter(cmd, "DomName", DbType.String, "xxxxx.net");
          db.AddInParameter(cmd, "Did", DbType.Int32, 500204);
        
          DataSet ds = db.ExecuteDataSet(cmd);
        }
        

        这会生成:

        exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
          N'@DomName nvarchar(9),
          @Did int',
          @DomName=N'xxxxx.net',
          @Did=500204
        

        您也可以在这里看到,如果引号字符作为参数传递,它们会被相应地转义:

        db.AddInParameter(cmd, "DomName", DbType.String, "'xxxxx.net");
        
        exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
          N'@DomName nvarchar(10),
          @Did int',
          @DomName=N'''xxxxx.net',
          @Did=500204
        

        【讨论】:

          猜你喜欢
          • 2011-10-19
          • 1970-01-01
          • 2011-07-12
          • 1970-01-01
          • 2018-03-29
          • 2019-06-05
          • 1970-01-01
          • 1970-01-01
          • 2019-08-03
          相关资源
          最近更新 更多