转义数据库对象名称
我需要在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