参数绑定:幕后发生了什么?

问题描述 投票:0回答:3

.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# sql .net database
3个回答
7
投票

有关准备好的语句的 MySQL 手册页提供了大量信息(应该适用于任何其他 RDBMS)。

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


0
投票

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


0
投票

如果您使用的是 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
© www.soinside.com 2019 - 2024. All rights reserved.