有人在这里使用过PostgreSQL的行级安全性(Row-Level Security, RLS)来实现租户隔离吗?
我最近正在构建一个多租户应用程序,但是最让我烦恼的事情就是通常使用的方法都是失败模式的。通过应用级别的过滤(自定义管理器,中间件将“.filter(tenant=….)” 注入其中),忘记了一个过滤器(例如在管理命令中,Celery 任务中,原始 SQL 查询中)意味着所有租户的数据都会返回。缺省就是“一切可见”,你需要在每个查询中都进行安全性选项。
不同租户所使用的模式解决隔离问题但是,随着规模的增加,我担心的是操作性方面的性能——迁移执行 N 次,级联膨胀,连接池复杂性。
RLS 以一种不同的角度来处理隔离:你在表中定义一个policy,然后 PostgreSQL在每个查询中执行它,无论这个查询是通过 ORM 和 raw SQL,还是 dbshell 执行的。如果会话中没有设置租户上下文,那么 policy 将评估为 false,结果将为零条数据—not all 条,仅仅是 zero 条。数据库就是安全性层,不需要你的应用程序代码来执行它。
我最终是构建了一个库来围绕它转:[django-rls-tenants]。模型都会从 RLSProtectedModel 中继承,政策在 migrate 过程中创建,中间件将 Pg Session 变量设置为租户所需的值,有一系列的上下文管理器用于后台的任务处理。它并不是对每种情景都完美适配的(PostgreSQL 有限制,不能自定义租户schema)但是,当实现“共享 schema,多租户”使用场景时,它已经很稳定了。
非常感谢您的回复,尤其是您之前尝试过 RLS 还是遇到过我应该注意到的边界情况。
评论 (0)