行和列安全
行和列安全仅在 Pro 和 Enterprise 计划中可用(包括自托管和 Metabase Cloud)。
行和列安全可让您为不同的人群提供细粒度的权限。您可以更改某个群组可以查看哪些数据,以及使用查询构建器可以查询哪些数据。
您可以使用行和列安全来设置自助服务分析,以便您的每个客户只能查看与其客户 ID 匹配的行。例如,如果您有一个包含客户信息的 Accounts 表,您可以为该表添加权限,以便每个客户仅查看与其相关的数据。
行和列安全以前称为数据沙盒。这是同一个功能,只是现在有了更具描述性的名称。
行和列安全示例
您可以跳过理论,直接查看行和列安全的示例。
行和列安全的工作原理
您可以将行和列安全视为一组权限,其中包括
- 将要替换原始表中所有在 Metabase 中使用的原始表的表的过滤版本。
- 应该查看过滤后表的群组。
您可以在 Metabase 中为每个表/群组组合定义最多一个行和列安全策略。这意味着您可以为不同的群组显示表的不同版本,例如为销售人员显示“销售账户”,为销售经理显示“经理账户”。
行和列安全类型
行和列安全根据个人的用户属性向其显示特定数据。您可以
| 目标 | 行(按表中的列过滤) | 自定义(使用已保存的 SQL 查询) |
|---|---|---|
| 通过过滤单个列来限制行 | ✅ | ✅ |
| 通过过滤多个列来限制行 | ❌ | ✅ |
| 限制列 | ❌ | ✅ |
| 编辑列 | ❌ | ✅ |
行级别安全:按表中的列进行过滤
您可以通过使用用户属性值过滤列来限制行。
例如,您可以为某个群组过滤 Accounts 表,以便用户属性过滤该表
- “Basic”将看到
Plan = "Basic"的行(即,Plan 列与值“Basic”匹配的行)。 - “Premium”将看到
Plan = "Premium"的行(即,Plan 列与值“Premium”匹配的行)。
自定义行和列安全:使用 SQL 查询创建自定义“视图”
要同时限制行和列,您可以使用 SQL 查询来过滤表。当有人查看该表时,他们将看到查询结果,而不是原始表。
例如,假设您的原始 Accounts 表包含以下列:ID、Email、Plan 和 Created At。如果您想隐藏 Email 列,可以创建一个“受限账户”SQL 查询,其中包含以下列:ID、Plan 和 Created At。
您可以使用查询来
行安全的前提条件
行安全会显示一个过滤后的表,以替换原始表,供特定群组使用。Metabase 如何过滤该表取决于每个人用户属性中的值。
例如,您可以设置行级别安全,以便用户属性 plan 根据不同值显示不同的行
- “Basic”将看到 Accounts 表的一个版本,其过滤器为
Plan = "Basic"(即,仅当 Plan 列与“Basic”值匹配时显示行)。 - “Premium”将看到 Accounts 表的一个不同版本,应用了
Plan = "Premium"的过滤器。
选择用于行和列安全的udent attributes
用户属性对于行安全是必需的,而对于列安全是可选的。在添加新的用户属性时,您将为每个人设置一个键值对。
Metabase 使用用户属性键查找特定个人的用户属性值。用户属性键可以映射到 Metabase 中的参数。
用户属性值必须与过滤器值精确匹配,且区分大小写。例如,如果您为 Accounts 表添加了行安全,并带有过滤器 Plan = "Basic",请确保将“Basic”作为用户属性值输入。如果您将用户属性值设置为小写的“basic”(该值在 Accounts 表的 Plan 列中不存在),则该用户将得到一个空结果而不是表。
用户属性应用示例
添加行级别安全
- 请确保先执行行安全的前提条件。
- 转到管理员设置 > 权限。
- 选择要保护的数据库和表。
- 找到要放入安全组的群组。
- 点击该群组的查看数据下的下拉菜单。
- 选择“行和列安全”。
- 点击列下的下拉菜单,然后输入要过滤表的列,例如“Plan”。
- 点击用户属性下的下拉菜单,然后输入用户属性键,例如“Plan”。
如果您有查询具有行级别安全的数据的 SQL 查询,请务必将所有这些查询移到仅管理员集合中。有关更多信息,请参阅您无法保护 SQL 结果的行或列。
查看行和列安全示例。
列安全的前提条件
- 一个群组。
- 一个仅管理员集合,其集合权限设置为对除管理员之外的所有群组无访问权限。
- 一个SQL 查询,其中包含要显示给群组人员的行和列,并存储在仅管理员集合中。
- 可选:如果您也想限制行,请为群组中的每个人设置用户属性。
创建 Metabase 显示的 SQL 查询而不是表
Metabase 将显示查询结果,而不是原始表,供特定群组使用。
使用 SQL 查询来定义要包含在自定义视图中的确切行和列。避免使用查询构建器(GUI)查询,因为您可能会意外地暴露额外数据,因为 GUI 查询可以包含来自其他查询或模型的数据。
确保将 SQL 查询保存在仅管理员集合中(集合权限设置为对除管理员之外的所有群组无访问权限)。有关更多信息,请参阅您无法保护 SQL 结果的行或列。
显示已编辑的列
除了排除行和列之外,您还可以显示已编辑的列(而不更改数据库中的列)。
例如,您可以创建一个“已编辑账户”SQL 查询,该查询截断 Email 列以显示用户名而不是完整的电子邮件地址。
如果您编辑了列,则 SQL 查询的架构(您想要显示的查询而不是表)必须与原始表的架构匹配。这意味着“已编辑账户”SQL 查询必须返回与原始 Accounts 表相同的列数和相应的数据类型。
您不能添加列。
设置列安全
- 请确保先执行前提条件。
- 转到管理员设置 > 权限。
- 选择要保护的数据库和表。
- 找到要限制的群组。
- 点击该群组的数据访问下的下拉菜单。
- 选择“行和列安全”。
- 选择“使用已保存的查询为该表创建自定义视图”。
- 选择您保存的查询。查询应以 SQL 编写。如果查询包含参数,则这些参数必须是必需的(不能是可选的)。
- 可选:根据用户的用户属性限制行。
您可以在行和列安全示例中找到示例设置。
使用 SQL 变量通过用户属性限制行
如果您设置了列安全,您还可以根据每个人的用户属性限制不同的行。例如,您可以为一组用户显示带有 Plan = "Basic" 过滤器的“账户”查询,为另一组用户显示带有 Plan = "Premium" 过滤器的“账户”查询。
- 请确保您已完成所有列安全的前提条件。
- 转到将显示给用户而不是表的 SQL 查询。
- 在 SQL 查询中添加参数化的
WHERE子句,例如WHERE plan = {{ plan_variable }}。 - 保存 SQL 查询。
- 转到管理员设置 > 权限。
- 找到要保护的群组和表。
- 打开查看数据下的下拉菜单。
- 点击编辑行和列安全。
- 向下滚动并设置参数或变量为 SQL 查询中的参数名称(例如,“Plan Variable”)。
- 将用户属性设置为用户属性键(例如,“User’s Plan”键,而不是值“Basic”)。
- 点击保存。
有关示例 SQL 变量和用户属性设置,请参阅行和列安全示例。
行限制与列安全的工作方式
标准的 WHERE 子句通过将列设置为固定值来过滤表
WHERE column_name = column_value
在上面行限制设置的第 2 步中,您将添加一个 SQL 变量,以便 WHERE 子句可以接受动态值。SQL 变量类型必须是文本、数字或日期。
WHERE plan = {{ plan_variable }}
在上面行限制设置的第 9-10 步中,您告诉 Metabase 将 SQL 变量 plan_variable 映射到用户属性键(例如“User’s Plan”)。Metabase 将使用该键查找与个人 Metabase 账户关联的特定用户属性值(例如“Basic”)。当该个人登录 Metabase 并使用受保护的表时,他们将看到按以下方式过滤的查询结果:
WHERE plan = "Basic"
请注意,用于创建自定义视图的 SQL 查询必须是必需的参数。例如,您不能使用可选参数;以下方法不起作用
[[WHERE plan = {{ plan_variable }}]]
了解更多关于SQL 参数
高级行级别安全:过滤具有多个 ID 的用户表
例如,假设您有如下表
| User_ID | 值 |
|---|---|
| 1 | 10 |
| 1 | 50 |
| 2 | 5 |
| 2 | 50 |
| 3 | 5 |
| 3 | 5 |
如果您想授予某人访问多个用户 ID 的权限(例如,该人应查看用户 ID 1 和 2 的行),您可以设置一个用户属性,例如 user_id,它可以处理逗号分隔的值,如“1,2”。
- 创建一个 SQL 查询,该查询解析逗号分隔的字符串并过滤表
SELECT *
FROM users_with_values
WHERE user_id = ANY(STRING_TO_ARRAY(REGEXP_REPLACE(TRIM({{user_id}}), '\\s*,\\s*', ','), ','))
此查询
- 修剪用户属性值中的空格
- 将逗号周围的任何空格替换为逗号
- 将逗号分隔的字符串转换为数组
- 过滤 user_id 匹配数组中任何值的行
STRING_TO_ARRAY() 和 REGEXP_REPLACE() 函数是 PostgreSQL 特有的。要查看您的数据库支持哪些函数,请参阅您数据库的文档。
- 使用此 SQL 查询设置行和列安全。请参阅设置列安全。
防止行和列安全权限冲突
某些 Metabase 权限可能与行和列安全冲突,从而导致比您预期的更宽松或更严格的数据访问。
假设您已为 Accounts 表设置了列安全,以隐藏 Email 列(针对特定群组)。
如果出现以下情况,Email 列可能会暴露给某人:
多个行和列安全权限
同一表上的多个行和列安全策略会造成权限冲突。您最多可以将一个人添加到每个表的行和列安全策略中的一个(通过该人员的群组)。
例如,如果您有
- 为“Basic Accounts”群组设置了安全,该群组在 Accounts 表上按
Plan = "Basic"进行过滤。 - 为“Converted Accounts”群组设置了另一个设置,该群组在 Accounts 表上按
Trial Converted = true进行过滤。
如果您将 Vincent Accountman 放入这两个群组,他将对 Accounts 表拥有冲突的权限,并且每次尝试在 Metabase 中使用 Accounts 时都会收到错误消息。
解决行和列安全权限冲突
- 将人员从除一个群组外的所有群组中移除。
- 将除一个群组外的所有群组的数据库查看数据访问权限设置为“阻止”。
您无法保护 SQL 结果的行或列
行和列安全权限不适用于 SQL 查询的结果。也就是说,SQL 查询将始终显示来自原始表的而不是受保护的表的结果。
假设您已为 Accounts 表设置了列安全以隐藏 Email 列。如果有人创建了一个包含 Email 列的 SQL 查询,任何有权限查看该 SQL 查询的群组都可以
- 在 SQL 查询结果中看到 Email 列。
- 使用 SQL 查询启动一个新的包含 Email 列的查询(如果他们有查询权限)。
为防止 Email 列通过 SQL 查询暴露
- 将任何包含 Email 列的 SQL 查询放入单独的集合中。
- 将集合权限设置为对已设置行和列安全以隐藏 Email 列的群组无访问权限。
集合权限必须用于防止受保护的群组查看引用受保护表的 SQL 查询。
公开分享
行和列安全权限不适用于公共查询或公共仪表板。如果未受保护群组中的某人使用原始表创建公共链接,则原始表将显示给任何拥有公共链接 URL 的人。
为防止这种情况发生,您需要禁用公共共享您的 Metabase。
Metabase 只能使用登录人员的群组成员身份或用户属性来创建行和列安全。由于公共链接不需要登录,Metabase 将没有足够的信息来应用权限。
行和列安全限制
使用行和列安全时的一些注意事项。
具有原生查询权限(访问 SQL 编辑器)的群组可以绕过行和列安全
行和列安全仅限于查询构建器。您不能为具有行和列安全的群组设置原生查询权限。
要使用原生查询编辑器强制执行行级别权限,请查看模拟。
您不能将行和列安全应用于 SQL 查询
由于 Metabase 无法解析 SQL 查询,SQL 查询的结果将始终使用原始表。
使用集合权限可防止群组查看包含受限数据的已保存 SQL 查询。
非 SQL 数据库的行和列安全有限
MongoDB 仅支持行级别安全。Apache Druid 不提供行和列安全权限。
高级数据类型需要解决方法
如果您尝试在具有高级数据类型(如枚举或数组)的列上设置行安全,您需要先将该数据转换为基本类型。选项包括
选项 1:使用 SQL 将高级数据类型转换为基本 SQL 类型
创建一个 SQL 查询,该查询将高级数据类型列转换为基本数据类型,然后将该查询用于您的行和列安全设置。
选项 2:创建数据库视图
如果您无法在 Metabase 中使用 SQL 转换,请在数据库中创建一个视图,将高级数据类型转换为基本类型,然后对该视图而不是原始表设置行和列安全。您还需要阻止原始表。
延伸阅读
阅读其他版本的 Metabase 的文档。