检查语句是否会在执行前更新记录

时间:2017-11-22 12:18:47

标签: sql sql-server

我有一个系统,它接受随机SQL语句并返回执行结果。我想限制系统执行只读语句并拒绝任何更新/插入/删除等任何记录的语句。

有没有办法向数据库询问语句是否为只读语句而没有实际执行它?

注意:

  • 只有少数人可以访问该系统。无论如何都有完全访问数据库的用户 - 所以我想要的是" oops"安全 - 我知道这不是处理SQL注入攻击等的方法。
  • 正则表达式验证可能过于复杂,因为"禁止的单词"如果它们在评论或列名中,则可以。例如 这应该是一个有效的输入:

    SELECT
      a AS update_value,
      'INSERT FOR FUN' AS q
    FROM t --comment: should we delete stuff?
    /*why not as long as you don't drop database*/
    

    但这应该被拒绝:

    UPDATE t SET a = 1
    
  • 我宁愿不创建单独的只读用户

3 个答案:

答案 0 :(得分:2)

我相信有两种解决方案:

  1. 您可以使用解析器sqlparserANTLR4来解析输入。然后很容易决定你有什么样的命令。 SQLParser在示例中有示例,说明如何对SQL命令进行分类。如果使用ANTLR4,则在使用gramar成功解析后获得解析树。如果你有一个SELECT语句,那么你必须在解析树中有select_statement gramar规则。

  2. 您可以使用SET SHOWPLAN_XML ON以XML格式获取估算的计划。在SQL Server返回的XML中,您具有StatementType属性,并且在您的情况下应该具有SELECT值。

答案 1 :(得分:1)

不是很优雅,当然也不是防弹 - 但我们实施过的是围绕可疑SQL语句的SELECT包装。

因此,如果您的用户输入

UPDATE t SET a = 1

然后我们将其包装成:

SELECT TOP 1 * FROM 
(
UPDATE t SET a = 1
)

如果SELECT包装器内的任何内容是updatedeleteinsert(更重要的是DROP TABLETRUNCATE,通常会产生错误等)。然后,您可以避免实际执行任何在很大程度上修改表的SQL语句。但是如果SQL语句是真正的SELECT语句,则没有错误,并返回1行。 (显然你可以修改或删除TOP 1以适应)

虽然对存储过程(等)不是很有用,并且有很多限制,但在我们的上下文中它是完美的解决方案。 (我们已经让用户能够在我们的应用程序中自由键入SQL)

答案 2 :(得分:1)

旧线程,但是有一个更好的解决方案,它看起来如此优雅,我还是想添加它:与其将SQL语句包装在select()中,而不是将其包装在“ begin transaction”和“ rollback”中。您仍然可以从查询中获得所有结果,但是无论发生什么(可能是邪恶的事情),它们都不会持久