2016-09-06 53 views
4

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

这是我通过检测查询的第一个单词的方法,但这似乎很脆弱。有没有更干净的方法来做这种检测?

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(); 
     } 
    } 
} 
+2

将整个事物包装在一个'TransactionScope'中,并且永远不会提交,所以无论他们做什么,都会回滚任何DML。 – Crowcoder

+5

您可以管理SQL Server上的用户权限吗?因为无论帐户在执行SQL,您只应授予SELECT权限。我认为这将是您提出的解决方案或任何基于“代码”的解决方案的首选解决方案。 – SimonGates

+0

为什么你让用户创建自己的SQL语句?这只是一个非常糟糕的主意。从sys.columns,sys.columns,sys.columns中选择*,整个系统就会瘫痪几个小时。对我来说,概念的证明应该是为什么永远不要让这种类型的应用程序靠近sql数据库。 –

回答

2

我会放弃尝试在应用程序代码中进行管理的任何尝试。而是使用SQL Server。

管理事情的一个好方法是执行以下操作。

  1. 创建一个新的模式。
  2. 创建一个数据库角色,该角色应拥有该模式。
  3. 创建视图在您想要公开的表上创建视图,即使它们是1:1它们应该在架构中。
  4. 将服务帐户添加到角色。

该服务帐户只能从视图中进行选择,并且您可以绝对控制您要公开的内容以及可以选择哪些数据。

即使对于其他开发人员和DBA,也可以轻松地进行搜索/审计。它还让您对任何架构更改的影响都有很好的看法。

+0

这将不会像书面工作。如果角色拥有架构并且其他人拥有基础对象,则所有权链将被中断,并且基础对象仍需要权限。 –

+0

接受这个,因为这是一种不能在代码中处理它的方法,也是一种更好的方法。我将以不同的方式管理权限,但这比首选应用程序更受欢迎。谢谢! –