提问人:jen 提问时间:10/27/2022 最后编辑:Mark Rotteveeljen 更新时间:10/27/2022 访问量:220
在不注入 SQL 的情况下将数据库名称传递给 SQL 查询
Passing database name to SQL query without SQL injection
问:
我需要在不注入 SQL 的情况下将数据库名称传递给我的 SQL 查询。
我首先获取所有数据库的列表,并检查我传递的数据库名称是否在列表中。如果是,我将转义我的数据库名称并将其传递给我的 SQL 查询。这是防止SQL注入的正确方法,因为我无法参数化数据库名称。另外,我应该如何处理异常?ArgumentException 可以吗?
public async Task<int> GetTableId(string database)
{
int res;
using (IDbConnection db = new SqlConnection(_settings.SqlServerConnString))
{
try
{
string sqlDatabases = $"SELECT [name] FROM [sys].[databases]";
List<string> resDatabases = db.Query<string>(sqlDatabases).ToList();
if (!resultDbList.Contains(database))
throw new ArgumentException(nameof(database));
var builder = new SqlCommandBuilder();
string sanitizedDatabase = builder.QuoteIdentifier(database);
string sqlId = $"SELECT DISTINCT [Id] FROM {sanitizedDatabase}.[dbo].[Table]";
res = db.Query<int>(sqlId).FirstOrDefault();
}
catch (Exception e)
{
_logger.LogError(e, "Error querying table id from database", new { database });
throw;
}
}
return result;
}
答:
1赞
Marc Gravell
10/27/2022
#1
无法对数据库进行参数化,因此留下的选项有限:
- 串联;根据您的示例,尽管建议使用它来处理空格等(尽管您还想检查!
[your db name here].whatever
]
- 通过语句(实际上并不比第一个选项更好,而且可移植性较差 - 而且它仍然需要是文字,而不是参数)
USE dbname;
- 在连接字符串中指定数据库,或通过用户的默认数据库指定数据库
不断将文本数据库名称连接到每个查询中将导致大量的字符串分配改动,因此,如果可以在连接级别(通过连接字符串)执行此操作,则效率可能会高得多。
评论
Id = @Id
USE someDB;
Initial Catalog=myDB