英文:
Sanitize user given column name in SQL Server via C#
问题
以下是您要翻译的代码部分:
public bool Set(int id, string columnName, object value)
{
/// <summary>
/// 此函数将给定的列名设置为给定的值,用于给定的 id。
/// 如果操作成功,则返回 true,否则返回 false。
/// </summary>
string query = "UPDATE " + TableName + " SET " + columnName + " = @value WHERE id = @id";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.AddWithValue("@id", id);
....
请注意,这段代码已经被翻译为中文。
英文:
In C# I have the following function:
public bool Set(int id, string columnName, object value)
{
/// <summary>
/// This function sets the given column name to the given value for the given id.
/// Returns true if the operation was successful, false otherwise.
/// </summary>
string query = "UPDATE " + TableName + " SET " + columnName + " = @value WHERE id = @id";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.AddWithValue("@id", id);
....
I cannot set columnName
as an parameter, that does not work. However the column name should be a user input. How can I make this sanitize?
I tried making columnName
an variable like this @columnName
and setting it later, however, this does not work because I think SQL Server interprets this as a string later, not a column object.
答案1
得分: 1
我感觉无论如何要写点东西,因为我不怎么写C#。但我确实想重申评论中的一切仍然是真实的;只是不要这样做。
话虽如此,如果您可以传递对象名称、ID和值作为参数,然后创建一个动态SQL语句,检查系统对象,可以做以下操作。这会导致类似于以下的一些(可怕的怪物):
String sql = @"DECLARE @SQL nvarchar(MAX);
SELECT @SQL = N'UPDATE ' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) + N' SET ' + QUOTENAME(c.name) + N' = @Value WHERE id = @Id;';
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.name = @Schema
AND t.name = @Table
AND c.name = @Column;
IF @SQL IS NOT NULL
EXEC sys.sp_executesql @SQL, N'@Id int, @Value nvarchar(4000)', @Id, @Value;
ELSE
THROW 56725, N'找不到要更新的对象。',16;";
try
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("@Schema",SqlDbType.NVarChar,128).Value = schemaName;
command.Parameters.Add("@Table",SqlDbType.NVarChar,128).Value = tableName;
command.Parameters.Add("@Column",SqlDbType.NVarChar,128).Value = columnName;
command.Parameters.Add("@Id",SqlDbType.Int).Value = idValue;
command.Parameters.Add("@Value",SqlDbType.NVarChar,128).Value = updateValue;
command.ExecuteNonQuery();
Console.WriteLine("更新完成。");
}
}
catch (SqlException e)
{
//引发适当的异常,我只是将错误输出到控制台
Console.WriteLine(e.ToString());
Console.WriteLine("更新失败。");
}
英文:
I felt like writing something for this anyway, because I don't write a lot of C#. I do, however, want to repeat that everything in the comments is still true; just don't do this.
That being said, what you can do if pass parameters for the object names, the id and the value, and then create a dynamic SQL statement, checking against the system objects. This results in some (awful abomination) like this:
String sql = @"DECLARE @SQL nvarchar(MAX);
SELECT @SQL = N'UPDATE ' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) + N' SET ' + QUOTENAME(c.name) + N' = @Value WHERE id = @Id;'
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.name = @Schema
AND t.name = @Table
AND c.name = @Column;
IF @SQL IS NOT NULL
EXEC sys.sp_executesql @SQL, N'@Id int, @Value nvarchar(4000)', @Id, @Value;
ELSE
THROW 56725, N'Object not found for update.',16;";
try
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("@Schema",SqlDbType.NVarChar,128).Value = schemaName;
command.Parameters.Add("@Table",SqlDbType.NVarChar,128).Value = tableName;
command.Parameters.Add("@Column",SqlDbType.NVarChar,128).Value = columnName;
command.Parameters.Add("@Id",SqlDbType.Int).Value = idValue;
command.Parameters.Add("@Value",SqlDbType.NVarChar,128).Value = updateValue;
command.ExecuteNonQuery();
Console.WriteLine("Update Complete.");
}
}
catch (SqlException e)
{
//Raise appropriate exception, I just dump errors to the console
Console.WriteLine(e.ToString());
Console.WriteLine("Update Failed.");
}
答案2
得分: 0
以下是代码部分的翻译:
一个简单的“消毒”输入的方法是尝试在系统表中查找表名和列名,然后使用参数化查询进行操作。
SELECT *
FROM SYS.SYSOBJECTS SO
JOIN SYS.SYSCOLUMNS SC ON SC.id = SO.id
WHERE SO.XTYPE = N'U'
AND SO.NAME = N'TABLE NAME'
AND SC.NAME = N'COLUMN NAME';
免责声明:我不太喜欢按照你目前的方式做事,也不太喜欢处理需要消毒的用户输入。你需要首先质疑这些事情。
英文:
A simple way to "sanitize" your input is to try to find the table name and column names in the system tables and do it using a parametrized query.
SELECT *
FROM SYS.SYSOBJECTS SO
JOIN SYS.SYSCOLUMNS SC ON SC.id = SO.id
WHERE SO.XTYPE = N'U'
AND SO.NAME = N'TABLE NAME'
AND SC.NAME = N'COLUMN NAME'
disclaimer: I'm not a big fan of doing things the way you are doing nor doing stuff that needs sanitized user inputs. You need to question those things first.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论