防止非select SQL语句

本文关键字:SQL 语句 select | 更新日期: 2023-09-27 18:06:01

我允许用户输入他们自己的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();
        }
    }
}

防止非select SQL语句

我将放弃任何试图在应用程序代码中管理这一点的尝试。而是使用SQL Server。

管理事情的一个好方法是这样做。

  1. Create a New Schema.
  2. 创建数据库角色,该角色应该拥有模式。
  3. 在你想要公开的表上创建视图,即使它们是1:1,它们应该在Schema中。
  4. 为角色添加服务账号

服务帐户只能从视图中进行SELECT,您可以绝对控制您要显示的内容和他们可以选择的数据。

这是很容易搜索/审计的,即使是其他开发人员和DBA。它还使您可以很好地了解任何模式更改的影响。