防止非SELECT SQL语句

时间:2016-09-06 19:52:28

标签: c# sql-server

我允许用户输入自己的SQL语句来执行,但前提是它只是一个SELECT语句。有没有办法检测SQL语句是否是除此之外的任何内容,即ALTER,INSERT,DROP等?我会担心其他问题,例如查询锁定表等等,但现在这更像是一个概念证明。我可以限制运行应用程序的服务器上的服务帐户对数据库具有只读权限,但我有兴趣在应用程序中查看它。

这是我通过检测查询的第一个单词来实现它的方法,但这似乎很脆弱。有没有更清洁的方法来进行此检测?

public void ExecuteQuery(string connectionString, int id)
{
    //The SQL statement will be user input
    var sql = "SELECT ColumnA, ColumnB, ColumnC FROM MyTable where MyTableId = @Id";
    var split = sql.Split(' ');

    if (split[0].ToUpper() != "SELECT") Console.WriteLine("Only use a SELECT statement.");
    else
    {
        using (var connection = new SqlConnection(connectionString))
        using (var cmd = new SqlCommand(sql, connection))
        {
            cmd.Parameters.AddWithValue("@Id", SqlDbType.Int);
            cmd.Parameters["@Id"].Value = id;
            connection.Open();

            var reader = cmd.ExecuteReader();
            try
            {
                while (reader.Read())
                {
                    Console.WriteLine($"{reader["ColumnA"]}, {reader["ColumnB"]}, 
                                       {reader["ColumnC"]}");
                }
            }
            finally
            {
                reader.Close();
            }

            cmd.ExecuteNonQuery();
        }
    }
}

1 个答案:

答案 0 :(得分:2)

我会废弃试图在应用程序代码中管理此操作的任何尝试。而是使用SQL Server。

管理事物的好方法是执行以下操作。

  1. 创建新架构。
  2. 创建数据库角色,角色应该拥有架构。
  3. 为要公开的表创建视图,即使它们是1:1也应该在Schema中。
  4. 将服务帐户添加到角色。
  5. 服务帐户只能从视图中进行选择,您可以绝对控制所公开的内容以及他们可以选择的数据。

    即使对于其他开发人员和DBA,这也很容易搜索/审核。它还可以让您更好地了解任何架构更改的影响。