我需要使用C#中的字符串连接来构建SQL Server 2016脚本(该脚本将通过ADO.NET执行)。我不能使用查询参数,我通常会这样做,因为脚本更像是一个安装脚本并包含不可参数化的语句。
以方式去逃避名称的方式:
"ALTER DATABASE " + Escape(databaseName) + " ADD ..."
不容易受到SQL注入攻击吗?如何实施Escape
?目前我在所有名称周围使用方括号,但是,当然这还不够......
答案 0 :(得分:2)
您可以使用QUOTENAME SQL Server内置函数来实现此目的。
因为它看起来非常像你在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?
答案 1 :(得分:1)
如果您使用常规.NET,请使用SqlCommandBuilder.QuoteIdentifier:
在正确的目录案例中给出一个不带引号的标识符,返回该标识符的正确引用形式。这包括正确转义标识符中的任何嵌入式引号。