2008-08-18 64 views
6

.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注入攻擊嗎?

回答

5

The MySQL manual page準備好的語句提供了大量的信息(這應該適用於任何其他RDBMS)。

基本上,您的語句被提前解析和處理,並且參數分別發送而不是與SQL代碼一起處理。這消除了SQL注入攻擊,因爲在參數設置之前解析SQL。

0

如果您使用MS SQL,請加載分析器,您將看到使用參數化查詢時生成的SQL語句。這裏有一個例子(我使用的是企業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 
0
在通俗地說

:如果一份準備好的聲明中發送,則數據庫會使用計劃(如果可用),這不不每次發送此查詢時都必須重新創建計劃,但只有參數的值已更改。這與procs的工作方式非常相似,procs的額外好處是你可以只通過procs授予權限,而不需要授予底層表的權限