𝗗𝗼𝗻'𝘁 𝗣𝗮𝗿𝘀𝗲 𝗦𝗤𝗟 𝘁𝗼 𝗠𝗮𝗸𝗲 𝗮 𝗤𝘂𝗲𝗿𝘆 𝗥𝘂𝗻𝗻𝗲𝗿 𝗥𝗲𝗮𝗱-𝗢𝗻𝗹𝘆

不要再试图通过检查 SQL 字符串中的关键字来保护你的数据库了。

如果你构建了一个运行 SQL 的工具,你会希望它有一个只读模式。你希望防止误操作的 UPDATE 导致数据丢失。你的第一反应可能是拦截 DELETE 或 DROP 之类的单词。

千万不要这样做。

字符串检查很容易被绕过。用户可以使用 WITH 子句来隐藏 DELETE。他们可以使用注释来隐藏命令。他们还可以调用一个会写入表的函数。你最终会陷入一场注定失败的“打地鼠”游戏。

让数据库来处理安全性。

Postgres 内置了处理此问题的功能。你可以将事务声明为只读。随后服务器会拒绝任何写入命令。这涵盖了 CTE、函数和 DDL。

以下是在 Python 中正确实现的方法:

这种方法不会检查 SQL 文本。查询会原封不动地发送到服务器。你是在告诉引擎去强制执行规则。

安全需要两个部分:

  1. 防止写入:使用只读事务。
  2. 防止资源滥用:使用超时和行数限制。

一个只读查询仍然可能因为一个巨大的 join 操作而导致系统崩溃。只读事务可以停止写入,但它无法阻止高强度的资源消耗。你需要两者结合才能确保 ad-hoc SQL 的安全。

停止解析 SQL。让数据库去做它该做的工作。

Source: https://dev.to/hitoshi1964/dont-parse-sql-to-make-a-query-runner-read-only-b62