2016-09-06 49 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

接受這個,因爲這是一種不能在代碼中處理它的方法,也是一種更好的方法。我將以不同的方式管理權限,但這比首選應用程序更受歡迎。謝謝! –