参数绑定:引擎盖下会发生什么?

时间:2008-08-18 17:11:15

标签: c# .net sql database api

.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注入攻击吗?

3 个答案:

答案 0 :(得分:5)

准备好的语句中的

The MySQL manual page提供了大量信息(适用于任何其他RDBMS)。

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

答案 1 :(得分:0)

如果您正在使用MS SQL,请加载探查器,您将看到在使用参数化查询时生成的SQL语句。这是一个例子(我正在使用Enterprise Libary 3.1,但结果是使用SqlParameters直接)对SQL Server 2005:

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

答案 2 :(得分:0)

通俗地说:如果发送了预先准备好的语句,那么数据库将使用一个计划(如果可用),每次发送此查询时都不必重新创建计划,但只有params的值具有改变。这与procs的工作方式非常相似,procs的额外好处是你可以只通过proc而不是基础表来提供权限