Supabase:列级安全解决方案

2023-12-21

目前,我正在使用 Supabase 数据库。我面临的一大障碍是列级安全性,这似乎比 RLS 复杂得多。

假设我有一个名为is_banned,可见但不可编辑。但是,其余列应该是可编辑和可查看的。

我真正能想到的唯一解决方案是将其分成两个表,并在“敏感信息”表上使用 RLS - 但为每个表创建一个私有表似乎相当不必要。

还有其他解决方案吗?


我必须自己处理这个问题。我目前用视图解决这个问题,但将来更愿意选择 RLS 策略、触发器或特权函数(截至目前尚未测试)。我在下面分享我对这个问题的研究笔记。


列级安全性(“CLS”)意味着根据某些条件有选择地禁止列值 UPDATE、INSERT 甚至 SELECT。有几种替代解决方案(summary https://dba.stackexchange.com/a/323514),各有利弊。下面详细讨论它们。

选项 1:RLS 政策

(到目前为止我最喜欢的选项,但我还没有在实践中使用它。)

在这里,对于防止更新的 CLS 策略,您将使用行级安全 (RLS) 策略来检索旧行并比较受保护列的字段值是否会从旧行更改为新行。此问题的候选解决方案已发布为堆栈溢出答案 https://stackoverflow.com/a/71167428,但这仍然需要做成通用函数。

乍一看,这似乎比触发器更好:它具有相同的优点,此外,Supabase 无论如何都提倡使用 RLS 策略进行访问控制,并且对 RLS 的 UI 支持比触发器好得多。因此,它将通过降低复杂性来提高数据库的一致性和可维护性。

但是,Supabase RLS 编辑器不能用于复杂的 RLS 策略(问题报告 https://github.com/supabase/supabase/issues/12443),因此作为一种解决方法,应该将所有 RLS 代码包装到单个或嵌套函数调用中,或者至少不超过一行代码。更好的是在 Supabase 外部的版本控制下维护 SQL 源代码,并在您想要更改 RLS 策略、表、函数等时将其复制并粘贴到 Supabase SQL 编辑器中。

选项 2:触发器

See here https://github.com/supabase/supabase/discussions/656#discussioncomment-4974429我原来的指示,然后改进的说明 https://github.com/orgs/supabase/discussions/656#discussioncomment-5594653作者:Github 用户 christophemarois。

优点:

  • 不添加另一个表或视图,因此数据库结构应该由数据决定,而不是由权限系统的怪癖决定。

  • 不需要更改默认的 Supabase 权限或表到架构分配。

  • 结合了 RLS 策略和列级权限的力量。

缺点:

  • Supabase UI 中尚未很好地支持触发器:只能更改触发器状态,但无法在 UI 中显示或编辑,只能在 PostgreSQL 控制台中显示或编辑。实际上,这并不是什么大问题,因为对于任何现实项目,您都必须直接使用 PostgreSQL 数据库。

  • 它需要 PGSQL 或其他编程语言的知识……对于某些人来说,我们希望使用 Supabase 避免编程。然而,该解决方案使用一个抽象函数来接收列到白名单(“允许更改”),因此不需要真正的编程,只需部署一些可重用的代码。

选项 3:特权函数

“您可以使用 SECURITY DEFINER 将表隐藏在 FUNCTION 后面。表本身不会提供 UPDATE 访问权限,用户只能通过 FUNCTION 更新表。” (source https://dba.stackexchange.com/a/323514)

在该函数中,您可以按照您喜欢的任何方式确定列级访问权限。模式中任何此类函数public可通过 API 自动获取:

“编写 PostgreSQL SQL 函数 [...] 并通过以下方式调用它们supabase.rpc('function_name', {param1: 'value'});." (source https://dev.to/davepar/going-serverless-with-supabase-103h).

但问题是,API 不再具有“所有内容都在表中可用”的统一结构。

选项 4:用户特定的视图

See the 指示 https://dba.stackexchange.com/a/301113。更多说明:

“您可以创建一个视图来仅显示您想要的列,请确保您使用WHERE语句,因为它会忽略 RLS(通常),然后使用 RLS 来阻止原始表。" (source https://github.com/supabase/supabase/discussions/8663#discussioncomment-3484271)

该解决方案已由 Supabase 维护者推荐 https://github.com/supabase/supabase/discussions/8663#discussioncomment-3484271。不过,总的来说,RLS 策略和触发因素似乎更可取。

为了使这个解决方案安全,您必须使用选项security_barrier = on (details https://www.postgresql.org/docs/current/rules-privileges.html),这会严重影响视图性能。解决这个问题的唯一方法是不使用WHERE子句,而不是通过以下方式重新使用基表的 RLS 策略security_invoker = on。这需要将基表移动到 API 未公开的自定义数据库方案(见下文)。

优点:

  • Simple.视图就像表一样,每个人都知道 PostgreSQL 表 - 与触发器或(复杂的)RLS 策略相反。

  • 您会看到您编辑的内容。可以看到表中记录的用户(或其应用程序)不必担心由于 RLS 策略而导致这些记录是否可编辑。用户可以看到任何内容,他们都可以编辑。

  • ❓ 可根据需要扩展。 (对此仍不确定。)视图中只能提供允许特定用户编辑的列。为了找到正确的列,有时需要更多上下文。没问题:在 API 访问时,根据需要再次连接底层基表中的视图和列。仅代理主键列id需要始终包含在视图中;这不是问题:如果用户尝试编辑它,则只有在使用新值时才能成功,在这种情况下,实际上会创建一条新记录,无论如何,用户可能都可以这样做。(有待确认的是,仍然可以进行具有适当访问保护的更新。)

缺点:

  • 使桌面空间变得混乱。理想情况下,API 将以正确的数据库设计中的形式公开数据。通过公开其他视图,API 会变得不必要的复杂。

  • 无法真正复用底层表的RLS策略。通过使用来完成security_invoker = on创建视图时(details https://github.com/supabase/supabase/discussions/901)。然而,在执行此操作时,可以通过视图更新记录的同一用户也可以更新基表中的该记录,从而规避使用视图的列访问限制。解决这个问题的唯一方法是将基表移动到 API 未公开的自定义数据库方案。这是可能的,但增加了更多的结构复杂性。

  • 需要更改默认查看权限。由于这些是简单视图,因此它们是 PostgreSQL 中的“可更新”视图。与 Supabase 模式 public 中默认的表级/视图级权限一起,这意味着所有用户,甚至匿名用户,都可以从这些视图中删除记录,从而导致底层表中的记录被删除。

    要解决此问题,必须从视图中删除 INSERT 和 DELETE 权限。这是对默认 Supabase 权限的更改,理想情况下是不必要的。

    有一个替代解决方案,但它不是很实用:您可以使用以下命令创建视图security_invoker = on重用底层表的RLS策略。然后使用这些 RLS 策略来防止记录删除。然而,他们必须允许 SELECT 和 UPDATE;因此,除非您将底层表移动到 API 未公开的架构,否则用户将可以绕过为其创建视图的列级安全性。

  • 没有好的办法来限制某些特定的使用 values 在某个列中向某些用户显示。这是因为视图不能有自己的 RLS 策略。有几种方法可以解决这个问题:

    • 解决这个问题的最佳方法可能是构建表,以便允许对列具有写访问权限的用户使用该列中的每个值。例如,代替列role(用户、管理员)和status(已申请、已批准、未批准),会有可为空的布尔列user_application, admin_application, user_status, admin_status.

    • 对于复杂情况,另一个选择是将基础表移动到 API 不可访问的自定义模式(同时仍然向所有 Supabase 角色授予使用和权限;see https://stackoverflow.com/a/73282539),在该基础表上创建 RLS 策略,并通过以下方式在视图中重用它们:security_invoker = on.

    • 对于复杂情况,另一种选择是在视图或底层表上使用触发器。

选项 5:列级访问权限

“您只能提供对表的一部分列的 UPDATE 访问:GRANT UPDATE(col1, col2)。(details https://stackoverflow.com/a/3281750)" (source https://dba.stackexchange.com/a/323514)

据报道,维护所有这些访问权限很麻烦。在 Supabase 中,不可能向不同的经过身份验证的用户授予不同的权限,因为所有用户都使用相同的角色访问数据库authenticated。不过,在 PostgREST 级别上工作时,您可以在此处有不同的选项。

选项 6:表拆分

与视图相比,这将主表分成多个部分。使用 RLS 策略,定义谁可以对每个部分表执行什么操作;而且,与只能在 WHERE 子句中部分模拟 RLS 策略的视图不同,RLS 策略还可以用于限制用户可以对列使用哪些值。要一起使用它们,必须将它们加入请求中。

将表格一分为二时非常好。但有时拆分几乎是“每列一张表”,例如每个角色一列的权限管理表。这很糟糕,因为它“原子化”了数据,而不是将其保持为适当的正常形式,这意味着管理员甚至无法以舒适的方式访问数据。这可以通过再次组合拆分表并提供对这些底层表的写入访问的视图来解决。但仍然有很多桌子需要处理。它很丑”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Supabase:列级安全解决方案 的相关文章

  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • 为 MongoDB 中的对象数组建立索引

    我有一个巨大的电子邮件转储 我正在尝试在 MongoDB 中存储和查询它 有 160 万封电子邮件 每封电子邮件都存储为节点模块 https github com andris9 mailparser它将原始电子邮件解析为漂亮的 Javas
  • PostgreSQL安装错误——无法分配内存

    我正在尝试从 sqlite3 切换到 PostgreSQL 以在 Rails 中进行开发 这样我就不会遇到任何 heroku 问题 我遵循了heroku和链接到的Railscast上给出的建议 但是在brew安装postgresql后遇到了
  • 数据库设计:类别在自己的表中?

    我正在将几个数据库重新设计成一个综合数据库 并且我注意到旧数据库的先前设计者喜欢将类别存储在自己的表中 例如 假设有一个表boats bid integer bname string color integer 并且在应用程序中有一个下拉框
  • 如何为 MySQL 和 Postgres 编写不区分大小写的查询?

    我在本地运行 MySQL 数据库进行开发 但部署到使用 Postgres 的 Heroku Heroku 处理几乎所有事情 但我不区分大小写的 Like 语句变得区分大小写 我可以使用 iLike 语句 但我的本地 MySQL 数据库无法处
  • 如何找到 Oracle 数据库的 URL?

    如何找到 Oracle 数据库的 URL 和端口 Example jdbc oracle thin host port dbName 用户名 密码 是否有我可以查看的 SQL 命令或日志 配置文件 对于甲骨文来说 有一个tnsnames o
  • 为什么 sql 字段名称中不应该包含逗号?

    人们一直告诉我列名中不应包含空格 我只是想知道 这是为什么 这是我为学校创建的一些数据库表遇到的问题 字段名称包括 Preble 和 Darke 相反 它们需要是 普雷布尔县 俄亥俄州 和 达克县 俄亥俄州 如果它们是行名称 我只需创建一个
  • 从数据库而不是配置文件中读取 CodeIgniter 配置值

    您可能知道 当您使用 CI 创建新项目时 您必须手动输入基本网址 加密密钥在config config php中 我正在努力克服这个问题 因此正在寻找一种方法read那些价值观而是从数据库中 为客户进行安装并设置时间作为一个整体decrea
  • WooCommerce:在数据库中查找产品

    我正在使用 WooCommerce 创建一个网站 我想根据用户在主页搜索表单中输入的邮政编码来限制用户可用的产品 为了能够实现这一目标 我必须在 phpMyAdmin 的数据库中指定每个产品的条件 但我似乎找不到它 有谁知道 phpmyAd
  • 使用连接查询检索行

    我有两张这样的桌子 A B col1 col2 col1 col2 一个表包含 300k 行 B表包含400k行 如果表 A 的 col1 与表 B 的 col1 匹配 我需要计算它 我写了一个这样的查询 select count dist
  • ER_ACCESS_DENIED_ERROR:用户 ''@'localhost' 的访问被拒绝(使用密码:NO)

    我有这个问题 我已经研究过但无法解决它 我想它与数据库权限有关 但我无法修复它 if error throw error Error ER ACCESS DENIED ERROR Access denied for user localho
  • Rails 多租户架构,限制多个租户的访问范围

    目前我们有一个单租户数据库架构 MySQL 运行着超过 100 个数据库 我们使用 Apartment gem 切换子域上的数据库连接 一切都很顺利 然而 我们现在需要创建所谓的 伞 客户端 它可以访问一组现有客户端的所有数据 我不认为这对
  • 使用 PHP 代码和 HTML 表单将 Excel (.csv) 导入 MySQL

    我知道还有其他类似的帖子 但每个人都建议直接在 PHPMyAdmin 中将其导入 MySQL 这工作完美 但我需要通过 HTML 表单导入 PHP 到 MySQL 我想要一个收集文件的 HTML 表单 然后将该文件传递给 PHP 脚本 我想
  • 需要有关使用 PHP 在 mysql 数据库中插入逗号分隔数据的帮助

    数据库表中已有的演示数据 INSERT INTO csvtbl ID SKU Product Name Model Make Year From Year To VALUES 1 C2AZ 3B584 AR Power Steering P
  • SQL 大表中的随机行(使用 where 子句)

    我有一个网站 人们可以在其中对汽车进行投票 向用户展示 4 辆汽车 他 她可以投票选出他们最喜欢的汽车 桌子cars有重要的列 car id int 10 not auto increment so has gaps views int 7
  • pq:无法调整共享内存段的大小。设备上没有剩余空间

    我在仪表板上有许多面板 数量约为 6 个 用于显示数据点图表 对 PostgreSQL 数据库的 Dockerized 实例进行查询 直到最近 面板都工作正常 有些面板停止工作并报告如下错误 pq 无法将共享内存段 PostgreSQL 2
  • DBeaver PostgreSQL 数据库 - 此驱动程序不支持 SCRAM 身份验证

    我正在尝试将 PostgreSQL 数据库添加到 DBeaver 但当我尝试连接到数据库时收到以下错误 我正在使用 DBeaver 版本 7 2 3 202010191702 收到此消息后 我安装了最新版本的 JDK 11 0 9 和 pg
  • 即使将“enable_seqscan”设置为关闭后,也未使用数组列上的 GIN 索引?

    根据推荐this https stackoverflow com questions 4058731 can postgresql index array columns comment10357041 4059785评论 我建立了一个 i
  • 如何在数据库中存储年月?

    是否有在数据库中存储年份和月份的标准方法 我需要根据月份和年份制作一些报告 我无法使用日期和函数实时提取月份 因为表很大 所以我需要预处理 我会和 Michael 的建议是什么 https stackoverflow com a 81694
  • 使用包含空值列的 WHERE 子句的更新语句

    我正在使用另一个表中的数据更新一个表上的列 这WHERE子句基于多个列 并且某些列为空 根据我的想法 这个空值是什么throwing off你的标准UPDATE TABLE SET X Y WHERE A B陈述 See 这个 SQL 小提

随机推荐

  • 制作用户定义的类 std::to_string-able

    我知道 Java 或 C 似乎太多了 但是 是否有可能 好 明智地使我自己的类有效作为函数的输入std to string 例子 class my class public std string give me a string of yo
  • 来自模板化对象的 Java 8 函数式构造函数

    我正在使用 Eclipse Luna Service Release 2 4 4 2 Java 8 u51 我正在尝试创建一个方法 该方法将根据另一个方法参数创建传递的对象的实例 原型简化为 public
  • 如何使用不可变数据类型实现 DFS

    我正在尝试找出一种 Scala 风格的图形遍历方式 最好使用 val 和不可变数据类型 鉴于下图 val graph Map 0 gt Set 1 1 gt Set 2 2 gt Set 0 3 4 3 gt Set 4 gt Set 3
  • 邪恶的pdf不渲染页眉/页脚

    我在用邪恶 pdf https github com mileszs wicked pdf用于生成pdf from html在我的 Rails 项目上 正在渲染template但我无法打印header footer部分 下面是我的仅打印的代
  • 无法从 Dropbox 下载文件

    我正在从 Dropbox 上传和下载文件 当我上传文件时 它会正确上传 当我下载文件并打开它时 该文件是零字节 有人能告诉我为什么会发生这种情况吗 下载代码 try File localFile new File localFilePath
  • 使用 LINQ 将项目移动到列表顶部

    有没有办法使用 LINQ 将 id 10 的项目移动为列表中的第一项 Item A id 5 Item B id 10 Item C id 12 Item D id 1 在这种情况下 我怎样才能优雅地将项目 C 移动到我的顶部List
  • Jquery 拖放,无需插件

    我尝试使用 JQuery 创建一个拖放插件 draggable on mousemove function var mouseposition this also needs to account for onclick offset of
  • 当目标系统关闭时,停止 Spring Cloud Stream @StreamListener 监听

    我有一个应用程序 它从 Kafka 获取消息并调用目标系统来更新旧版 Oracle 数据库 我想要启用一个场景 如果目标系统关闭 则将消息留在 Kafka 总线上 并且在给定的时间内不处理它们 我正在考虑一些基于 Hystrix 的断路器解
  • 我们可以在 swing 中开发非常漂亮的 UI吗?如果不能的话有什么替代方案

    在我当前的项目中 我们必须用 java 开发一个漂亮的基于桌面的应用程序 目前 我们有一个用 swing 编写的非常基本的桌面应用程序 并且团队没有很好的 swing 知识 我们能在 swing 中创建一个非常好看的 UI 吗 我们应该使用
  • 使用 select() 实现超时

    我只能在 select API 中将超时参数设置为最多 20 秒 无论我给出的值高于 20 select 都会在 20 秒后返回 所以我试图写一个超时 1 分钟的循环 如下所示 int timeoutcount 0 do FD ZERO f
  • 将尽可能多的事件纳入时间表的算法

    我正在尝试找到一种算法 可以将尽可能多的非重叠事件安排到时间表中 其中可以根据需要在时间表中添加或删除任何这些事件 这些事件都不能重叠 但我想将尽可能多的事件纳入每日日程中 12 00 PM 12 45 PM Lunch 1 00 AM 3
  • 如何在 C++ 中使用 GLUT / OpenGL 绘制文本?

    如何使用 GLUT OpenGL 绘图函数在屏幕上绘制文本字符串 用GLUT绘制字符串有两种方法 glutStrokeString https linux die net man 3 glutstrokestring将绘制 3D 文本 so
  • 访问 SQL - 更改列以自动编号?

    如何使用 SQL 更改 MS Access 中的表以将数据类型更改为自动编号 我尝试跟随但没有成功 ALTER TABLE PERSON ALTER COLUMN PERSON ID Integer PRIMARY KEY counter
  • PHP MySQL INSERT 不插入也不显示任何错误

    我已经得到了这段代码 因此可以通过 PHP 将值插入 MySQL 中的表中 我已经尝试了所有可能的插入语法 它不插入数据 这是我使用的代码 param xyzxyz param1 sdfdfg sql INSERT INTO trail U
  • Angular JS 表中嵌套 ng-repeat

    我是 Angular JS 的新手 我一直在尝试迭代模型集合并将其显示在表格中 该模型看起来像 var myModule angular module myModule controller myController function sc
  • 如果安装了 Visual Studio 2010,我可以使用 XNA 创建游戏吗?

    非常简单的问题 谢谢 作为一个学究 是的 你可以 只是不在 VS 2010 内部 你可以并行安装 2008 Express 版本并使用它 直到他们更新 2010 年的 XNA
  • android.intent.action.MAIN 的含义是什么?

    我见过很多不同的令人困惑的解释
  • 如何强制 IIS Express 在 32 位模式下运行?

    我有一个经典的 ASP 应用程序 我试图在 64 位 Windows 上的 IIS Express 下运行它 它使用 Jet 连接到 Microsoft Access 数据库 并且无法在 64 位下运行 我为 ASP 应用程序创建了以下应用
  • 如何同时给图片添加对比度、亮度等多种效果

    我使用 python 创建了一个简单的程序来更改图片对比度 亮度颜色等 首先 我只添加了一个效果 效果很好 我设法将其与缩放器链接 然后我尝试一次添加多种效果 我也与缩放器链接 但是当我尝试在图片上添加多种效果 例如同时对比度和亮度 时 我
  • Supabase:列级安全解决方案

    目前 我正在使用 Supabase 数据库 我面临的一大障碍是列级安全性 这似乎比 RLS 复杂得多 假设我有一个名为is banned 可见但不可编辑 但是 其余列应该是可编辑和可查看的 我真正能想到的唯一解决方案是将其分成两个表 并在