繁体   English   中英

在每个查询中将属性设置为特定值

[英]Have attribute set to specific value on every query

设置:

我使用psycopg2访问我在 SQL 中构建的 (PostgreSQL) 数据库。我希望有不同的用户,它们只能访问表中自己的行。 因此,我向方案中的每个表添加了一个UserId属性。 UserId 的值可作为变量(让我们将其命名为pyUserId )提供给执行的程序。 我通过我定义的一个 function 对curs.execute() go 的所有调用。

我想要实现的目标:

我是否可以为每个查询集中设置一个属性的值,比如UserId=pyUserId 否则我必须将 pyUserId 作为我已经构建的每个查询的数据传递,我怀疑这也违反了 DRY。

例如:
SELECT UserName FROM Users WHERE Age < 30变为:
SELECT UserName FROM Users WHERE Age < 30 AND UserId = pyUserId
或者
INSERT INTO Profiles (Name, Bio, SoAccount) VALUES ('jon', 'blah...', '22656')变成
INSERT INTO Profiles (Name, Bio, SoAccount, UserId) VALUES ('jon', 'blah...', '22656', pyUserId)

DELETE等相同。

我尝试了什么:

  • 对于INSERT ,可以动态更改 PostgreSQL DEFAULT 约束。 但这只适用于插入。
  • 根据 psycopg2 文档中的字符串组成,我可以操作 SQL 查询字符串。 但是估计坑不少,操作SQL个字符串。
  • 然而,也许有一种方法可以通过操纵准备好的语句或分析树来做到这一点。
  • 我不确定这个想法是否可行。 如果不是,请解释原因。

Snakecharmer 的评论帮助我实现了以下内容。

在特定行属于特定用户的所有表中都有一个属性UserId

CREATE TABLE Users (
    UserId INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    user_attributes ...

CREATE TABLE some_table (
    UserId INTEGER REFERENCES Users(UserId) 
    DEFAULT current_setting('my_app.CurrentUserId')::INTEGER NOT NULL,
    some_attribute INTEGER, ...

基于本教程:定义一个 session 变量,当用户通过身份验证并在上面用作DEFAULT时设置该变量:

SQL = "SET my_app.CurrentUserId = %s"
data = (self.__userId, )
cur.execute(SQL, data)

实施Row-Level Security ,以创建仅允许访问UserId等于 session 变量的策略:

DO -- Create a loop over all tables to create a policy and enable it for them
$$
DECLARE
    row record;
BEGIN
    FOR row IN SELECT tablename FROM pg_tables AS t
        WHERE t.schemaname = 'public' 
        AND NOT t.tablename ~* 'exclude|tables|regex'
    LOOP
        EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY;', row.tablename); 
        EXECUTE format('CREATE POLICY isolateUserId ON %I TO some_user 
                            USING (UserId = current_setting(''my_app.CurrentUserId'')::INTEGER);', row.tablename); -- Escape ' !
    END LOOP;
END;
$$;

怎么运行的:

  • 这很有效,因为只有少数表没有获得 RLS,所以它们可以很容易地在正则表达式中删除。
  • some_user是您在 psycopg2 中用来连接数据库的用户。
  • 我为循环复制了这个答案
  • 它的工作方式在链接文章中有很好的解释。 TL;DR:通过 session 变量和默认值的组合,确保用户始终使用自己的 UserId 创建项目。 Session 变量和策略确保用户只能看到/更改/删除他们自己的 UserId 所在的行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM