在限制用户权限的同时动态执行DDL语句的方法

时间:2017-12-22 07:22:13

标签: database postgresql asp.net-core

所以我正在尝试使用带有PostgreSQL数据库的.NET Core 2开发Web应用程序,我需要能够记录大量数据。以前我使用动态生成的语句来对数据库执行DDL操作。动画元素以粗体显示的示例:

  

DO LANGUAGE plpgsql $$ BEGIN IF(选择to_regclass(' public.item [唯一编号]'))IS NULL然后创建表如果不是EXISTS项[唯一编号](签名字符变化(50),项目名称字符变化(50)......等

每个表包含大约50个具有特定参数的列。每个项目表包含多个动态行项目类型,并具有各自的列值。

问题是我觉得像这样的动态语句生成是一个巨大的安全漏洞。也许我错了,但感觉就是这样。

我想出了两个选择:

1)创建50个表,表示每个表的前一列,然后在所有50个表中插入INSERT,并在SELECT语句中为所有表进行JOIN。 (我关心的是这会如何影响性能而不是简单地从1个表中选择所有。我也担心如果其中一个表被破坏/等会影响很多项目,而旧的方式一个损坏的表只影响1个项目。)

2)预先生成大量空表,然后根据需要将记录INSERT到每个空表中,同时跟踪另一个表中的表名。如果需要,存储过程可能会定期生成更多。 (这对我来说就像是一个黑客。)

是否有人建议如何存储此数据,同时避免客户端发送动态DDL语句?

1 个答案:

答案 0 :(得分:0)

你可以保存plpgsql来代替并接受争论。您也可以使用format来避免注入,最后您可以检查此列是否存在,例如:

t=# create or replace function ct(_n text) returns void as $$
begin
select attname into _n from pg_attribute where attname = _n;
if _n is not null then
  execute format('create table if not exists %I()','item'||_n);
end if;
end;
$$ language plpgsql;
CREATE FUNCTION

现在:

t=# select ct(e'\';--hack');
 ct
----

(1 row)

Time: 2.202 ms
t=# \dt item*
No matching relations found.

如果列有效:

t=# select ct('a');
 ct
----

(1 row)

t=# \dt item*
       List of relations
 Schema | Name  | Type  | Owner
--------+-------+-------+-------
 public | itema | table | vao
(1 row)