我需要在C#中使用字符串連接來構建SQL Server 2016腳本(該腳本將通過ADO.NET執行)。我不能使用查詢參數,我通常會這樣做,因爲腳本更像是一個設置腳本幷包含非可參數化的語句。轉義數據庫對象名稱
什麼的的方式去逃避名這樣的:
"ALTER DATABASE " + Escape(databaseName) + " ADD ..."
不容易受到SQL注入?如何實現Escape
?目前我在所有名稱周圍使用方括號,但是,這當然是不夠的...
我需要在C#中使用字符串連接來構建SQL Server 2016腳本(該腳本將通過ADO.NET執行)。我不能使用查詢參數,我通常會這樣做,因爲腳本更像是一個設置腳本幷包含非可參數化的語句。轉義數據庫對象名稱
什麼的的方式去逃避名這樣的:
"ALTER DATABASE " + Escape(databaseName) + " ADD ..."
不容易受到SQL注入?如何實現Escape
?目前我在所有名稱周圍使用方括號,但是,這當然是不夠的...
您可以使用SQL Server內置函數QUOTENAME來實現此目的。
因爲它看起來非常像在C#中構建腳本,所以在使用SQL執行它之前,您可能希望擁有一個C#函數,它可以訪問數據庫以執行此操作,也許還將結果值存儲在Dictionary<string, string>
中以消除已經引用的字符串的往返行程。
例如:
private Dictionary<string, string> _quotedNames = new Dictionary<string, string>();
private string GetSqlQuotedName(string name)
{
if (!_quotedNames.ContainsKey(name))
{
_quotedNames[name] = GetSqlQuotedNameFromSqlServer(name);
}
return _quotedNames[name];
}
private string GetSqlQuotedNameFromSqlServer(string name)
{
/// Code here to use your Data access method of choice to basically execute
/// SELECT QUOTENAME(name) and return it
}
其實,只是爲了顯示這個在System.Data.SqlClient命名空間中的類,下面是執行這種行爲,給使用通話連接字符串當一個類到SQL Server:
public class SqlNameEscaper
{
private Dictionary<string, string> _quotedNames = new Dictionary<string, string>();
private string _connectionString = string.Empty;
public SqlNameEscaper(string connectionString)
{
_connectionString = connectionString;
}
public string GetSqlQuotedName(string name)
{
if (!_quotedNames.ContainsKey(name))
{
_quotedNames[name] = GetSqlQuotedNameFromSqlServer(name);
}
return _quotedNames[name];
}
private string GetSqlQuotedNameFromSqlServer(string name)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var command = new SqlCommand("SELECT QUOTENAME(@name)", connection))
{
command.Parameters.AddWithValue("@name", name);
var result = command.ExecuteScalar();
return result.ToString();
}
}
}
}
這然後可以通過做這個被稱爲:
var sne = new SqlNameEscaper(@"CONNECTION_STRING_HERE");
var bracket = sne.GetSqlQuotedName("[");
或者,在你的榜樣的背景:
var sqlNameEscaper = new SqlNameEscaper(@"CONNECTION_STRING_HERE");
var text = "ALTER DATABASE " + sqlNameEscaper.GetSqlQuotedName(databaseName) + " ADD ...";
還有上dba.stackexchange.com這是值得擁有的關於這個主題的讀取問題:Should we still be using QUOTENAME to protect from injection attacks?
是QUOTENAME也可用於「參數」,如'ADD FILE(name ='
@DR - 可能,儘管您更有可能開始達到128個字符的限制,即d任何提及。如果你使用我上面提出的包裝函數,那麼結果字符串可以用在你想要的任何地方! =) – Rob
你可以驗證這些變量對某些檢查不要忘記[];和「etc – BugFinder
@BugFinder,雖然醜陋和錯誤,可怕,並[在這裏插入更多的形容詞],這是完全合法*有一個名爲'[''在SQL Server中的表格=( – Rob
真實的,但你可以使它成爲一個要求對於你的應用:)你不用:D – BugFinder