使用Django和Postgresql实现分离模式的层次化多租户架构

3

我有一个 Django 应用程序,其中包含客户和多个与这些客户相关联的用户,我想将该系统迁移到分层的多租户架构。

分层部分

客户可以递归地包含其他客户。例如,客户 A 包含 客户 B客户 C。如果用户 客户 A 登录系统,用户将看到 客户 B客户 C 的数据。如果 客户 B 的用户登录系统,则用户只能看到 客户 B 的数据。

多租户部分

我希望将所有客户的数据存储在单独的模式中。但是有一些数据与客户无关,因此我希望将这些数据存储在“public”模式中。

当我研究使用 Django 构建多租户应用程序时,我看到了这部分内容:

def set_tenant_schema_for_request(request):
    schema = tenant_schema_from_request(request)
    with connection.cursor() as cursor:
        cursor.execute(f"SET search_path to {schema}")

然而,为了应用我之前提到的层级示例,我必须同时访问多个模式。我能做到吗?还是有其他实现架构的方法?

1个回答

1
您可以在PostgreSQL搜索路径中列出多个模式。如果相同的表出现在几个模式中,只会返回搜索路径中第一个模式中的行。不会自动合并来自不同模式中的表中的行。所以这可能不是您想要的。您可以重新设计应用程序,以便每个查询从不同模式的表中选择数据,然后使用union子句将这些结果连接在一起。虽然这样做会提供正确的结果,但应清楚地看到,以这种方式构建所有查询将极大地复杂化应用程序,因此也不是一个好计划。如果您希望能够同时查看来自多个客户端的数据,则具有隔离模式的多租户架构不是正确的方法。排除了其他选择后,我认为只剩下一种方法。您必须使用共享模式多租户,其中来自不同客户端的行存储在相同的表中。具有共享模式意味着来自不同客户端的数据分离较少,但它提供了一种简单的方法,在需要显示多个客户端的数据时同时显示这些数据。实现的常规方法是向查询的where子句添加术语,以确保仅返回适用于已登录用户的数据。
另一个可能性是在数据库中使用行级安全性。采用这种方法,每个客户端都会有自己的Postgres用户帐户,并具有限制访问仅适用于他们的行的策略。这将一些确保正确安全性的责任从应用程序层推向数据库层,这有利有弊。好处是安全性只需在数据库中实现一次,而不是在应用程序的数据访问部分中实现。可能的缺点是数据库需要做更多的工作。

https://www.postgresql.org/docs/11/ddl-rowsecurity.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接