【问题标题】:Parse a SQL statement to see if it is anything other then a SELECT statement?解析 SQL 语句以查看它是否是 SELECT 语句以外的任何内容?
【发布时间】:2011-05-07 08:36:10
【问题描述】:

有没有一种很好的方法来解析 SQL 语句以确保它只包含一个 SELECT 语句而没有其他内容?我正在使用 C#、System.Data.SqlConnection 和 MS SQL Server

【问题讨论】:

    标签: c# sql-server sqlconnection query-parser


    【解决方案1】:

    我认为解析 sql 将是解决方案: from another question

    【讨论】:

    • 即使使用 ANTLR,这仍然非常困难并且极易出错。 (你需要一个完整准确的语法)
    • 同意,但它确实优于在查询字符串中搜索单词“SELECT”。我想知道,如果您使用的是 SQLCommand 对象,是否可以在执行前检查 CommandType 属性?
    • 没有。 CommandType 允许您指定文本是查询还是存储过程。它永远不会自动设置。
    • 真可惜。您会认为,在整个 SQL 服务器命名空间可用的情况下,您将能够在其中找到解析器!
    【解决方案2】:

    我猜你可以想出一个正则表达式,但它可能不是 100% 安全的。

    最好的方法是:
    1. 要么编写存储过程和视图,并且限制用户的权限只能使用它们。 (以及某些表上的 SELECT 语句)
    2. 构建数据抽象层。您构建查询,而不是其他人。让其他人只访问您公开的一些方法。
    3. 使用 LINQ to SQL,但隐藏 DataContext 对象,因此不能对数据库进行任何更改。

    【讨论】:

    • sql 语句需要是动态的,所以 sprocs 出来了。它是一个 QueryBuilder 引擎,它允许用户从数据库中选择几乎任何东西。我也更愿意避免使用 LinqToSql,因为管理员用户是定义可以从数据库中选择的内容的用户,而不是我。
    【解决方案3】:

    您应该以除SELECT 之外无权执行任何操作的用户身份连接到数据库。

    这样,任何非SELECT的语句都将无法执行。

    这是最安全的解决方案,没有复制 SQL Server 的解析器。

    【讨论】:

    • 我能否在 SQL Server 2005/2008 上创建一个用户,该用户除了可以运行任何 SELECT 命令之外还可以运行存储过程?
    • 几乎+1..这可能是最安全的方式,但它不能直接回答问题..
    • 我会说这是一个“X/Y 问题”......而这个答案解决了 X。
    • @Rachel - 请注意,如果对存储过程具有 EXECUTE 权限的用户可以执行修改数据的存储过程,他可能能够修改数据 - 即使用户没有任何除了 SELECT 之外的其他权限。
    • @Miky,这个问题的直接答案是一个太大、太复杂、太重且不确定实际考虑的解决方案。
    【解决方案4】:

    检查以确保语句以 SELECT 关键字开头,然后确保该语句不包含不是文字字符串一部分的分号(这将开始另一个 SQL 语句)。

    【讨论】:

    • SQL Server 不需要分号来分隔语句
    • 检查“不属于文字字符串的分号”意味着分析语法,正如一些 cmet 对其他答案所述,select 语句可能以“WITH”开头...
    • @Rachel 真的吗?用分号分隔语句是 SQL 标准的一部分。不要喜欢让您在 TSQL 语言中使用不同终止符的 GUI。
    • @chiccodoro:是的,意思是分析语法。不分析语法怎么知道是什么语句?
    • @gmagana - 我想是的...我可以在新查询窗口的一行中写上select 1 select 1,并将其作为两个单独的命令执行
    【解决方案5】:

    由于 SELECT 语句需要位于语句的最开头,因此您只需检查字符串以查看前 6 个字符是否为 SELECT:

    if (stringSql.Substring(0, 6).ToUpper() == "SELECT")
    {
        //execute statement
    }
    

    【讨论】:

    • 这会失败。我可以写 SELECT * FROM Users;从用户中删除;
    • 如果查询使用 CTE,它将以 WITH 开头,而不是 SELECT
    • 好点...但贾斯汀是对的;你应该能够使用参数来保护自己。
    • 我不能使用参数,因为语句需要是动态的
    • @JustinNiessner 如果我们检查该语句不包含任何“DELETE、INSERT、UPDATE、DROP”调用怎么办?这足以将其标记为读取请求吗?当然它不会 100% 准确,但我相信它在许多情况下都是可以容忍的。
    猜你喜欢
    • 2021-09-05
    • 2017-01-16
    • 2017-03-03
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多