Power BI 中的行级安全性:多租户数据访问

在 Power BI 中实施行级安全性以实现多租户访问控制。静态和动态 RLS、DAX 筛选器、OLS、DirectQuery 和嵌入式场景。

E
ECOSIRE Research and Development Team
|2026年3月17日6 分钟阅读1.2k 字数|

Power BI 中的行级安全性:多租户数据访问

行级安全性 (RLS) 是一种确保每个用户只能看到他们有权访问的数据的机制。在多租户或多部门环境中,RLS 不是可选的——它是受监管的分析平台与即将发生的数据泄露之间的区别。然而,Microsoft 自己的使用情况遥测表明,只有不到 30% 的拥有 Power BI Premium 的组织在其生产数据集上实施了 RLS。

原因并不是 RLS 在概念上很困难。原因是实现细节非常微妙,测试过程是手动的,而且 RLS 和其他 Power BI 功能(DirectQuery、复合模型、嵌入、聚合)之间的交互会产生让团队措手不及的边缘情况。本指南涵盖了 RLS 实施的各个方面,从最简单的静态角色到与 Azure Active Directory 集成的复杂动态安全性。


要点

  • Power BI 中的行级安全性使用 DAX 表达式在模型级筛选数据,确保用户无法通过修改报告或视觉效果来绕过安全性
  • 静态 RLS 硬编码过滤器值(适合小型、稳定的用户组),而动态 RLS 使用 USERNAME() 和 USERPRINCIPALNAME() 等 DAX 函数根据登录用户进行动态过滤
  • RLS 仅适用于导入和 DirectQuery 模式 --- 它不适用于与 Analysis Services 的实时连接(它有自己的 RLS)
  • 对象级安全性 (OLS) 隐藏整个表或列,为用户甚至不应该知道某些数据存在的场景补充 RLS
  • 测试 RLS 需要 Power BI Desktop 和服务中的“查看为”功能 --- 切勿在未对每个角色进行显式测试的情况下假设 RLS 可以正常工作
  • 嵌入式场景(Power BI Embedded)中的 RLS 需要在嵌入令牌中传递有效身份,这是实现错误的常见来源
  • 对于设计良好的模型,RLS 的性能影响通常小于 5%,但编写不当的 DAX 过滤器可能会使性能降低 50% 或更多

了解行级安全性

RLS 的作用

RLS 将 DAX 筛选表达式应用于 Power BI 数据模型中的一个或多个表。当用户打开报表时,Power BI 会评估 RLS 规则并以静默方式筛选出用户无权查看的行。用户体验到正常的报告——他们根本无法看到超出其范围的数据。

重要的是,RLS 在数据模型层运行,而不是在报告层。这意味着:

  • 用户无法通过在同一数据集上创建自己的报告来绕过 RLS
  • RLS 过滤器通过关系传播(Dim_Region 上的过滤器自动通过关系过滤 Fact_Sales)
  • DAX 度量尊重 RLS 上下文(CALCULATE、SUMX 和其他函数对过滤的子集进行操作)
  • 导出到 Excel、CSV 或 PowerPoint 仅导出用户有权查看的数据

RLS 与其他安全机制

机制范围执法
工作区访问谁可以看到工作区Power BI 服务
应用程序权限谁可以访问已发布的应用程序Power BI 服务
行级安全用户看到哪些行数据模型(DAX)
对象级安全用户看到哪些表/列数据模型(元数据)
敏感度标签分类与保护微软权限
数据导出限制用户是否可以导出数据报告/工作区设置

RLS 是控制用户可以访问哪些特定数据行的唯一机制。其他机制控制工作区、报表或对象级别的访问。


静态行级安全性

静态 RLS 使用硬编码的过滤器值将用户分配给角色。这是最简单的实现方式,适用于少数固定区域、部门或业务单元的场景。

创建静态角色

在 Power BI 桌面中:

  1. 转到建模,然后管理角色 2.点击创建添加新角色
  2. 命名角色(例如“北美销售”)
  3. 选择要过滤的表(例如 Dim_Region)
  4. 编写DAX过滤表达式:
[Region] = "North America"

该表达式的意思是:当用户被分配“北美销售”角色时,与 Dim_Region 相关的每个表将仅显示区域为北美的行。查看销售报告的用户只能看到北美销售情况。查看 HR 仪表板(如果通过区域维度连接)的用户将仅看到北美员工。

多重角色

您可以使用不同的过滤器创建多个角色:

  • 欧洲、中东和非洲销售[Region] = "EMEA"
  • 亚太地区销售[Region] = "APAC"
  • 全球执行官:无过滤器(查看所有数据)

一个用户可以被分配多个角色。当分配给多个角色时,过滤器与 OR 逻辑相结合——用户看到所有角色数据的并集。例如,分配给“北美销售”和“欧洲、中东和非洲销售”的用户会看到这两个区域的数据。

静态 RLS 的局限性

在以下情况下,静态 RLS 变得难以管理:

  • 您有超过 10-15 个不同的过滤器值(创建和维护 15 个以上的角色很乏味)
  • 用户到角色的分配经常更改(每次更改都需要 Power BI 管理员)
  • 过滤逻辑比简单的相等更复杂(例如,管理者应该看到他们团队的数据加上他们自己的数据)
  • 您在数十个业务部门拥有数百名用户

对于这些场景,动态 RLS 是解决方案。


动态行级安全性

动态 RLS 使用在运行时评估的 DAX 函数来确定登录用户并应用适当的筛选器。两个关键功能是:

  • USERNAME() — 返回当前用户的域\用户名或 UPN
  • USERPRINCIPALNAME() — 返回当前用户的电子邮件/UPN(建议用于云部署)

设置动态 RLS

第一步:创建安全映射表

该表将用户映射到其授权数据范围。它可以存储在数据源(数据库)、SharePoint 列表或 Excel 文件中:

用户邮箱地区部门公司编号
[email protected]北美销售1
[email protected]欧洲、中东和非洲销售2
[email protected]亚太地区运营3
卡罗尔@company.com全部全部全部

将此表作为 SecurityMapping 导入到 Power BI 模型中。

步骤 2:创建 RLS 角色

在安全映射表上使用 DAX 过滤器创建单个角色(例如“DynamicSecurity”):

[UserEmail] = USERPRINCIPALNAME()
    || [UserEmail] = "ALL"

第 3 步:建立关系

建立从 SecurityMapping 到维度表的关系:

  • SecurityMapping[区域] 到 Dim_Region[区域]
  • SecurityMapping[部门] 到 Dim_Department[部门]
  • SecurityMapping[CompanyId] 到 Dim_Company[CompanyId]

这些关系从维度到安全映射表必须是一对多,或者您可以使用双向交叉过滤器。然而,双向过滤器对性能有影响——更好的方法是在 DAX 表达式中使用 CROSSFILTER 或 TREATAS。

步骤 4:没有关系的替代方案(TREATAS 方法)

您可以直接在事实表的 RLS 表达式中使用 TREATAS,而不是从安全映射表创建关系:

VAR CurrentUser = USERPRINCIPALNAME()
VAR UserRegions =
    CALCULATETABLE(
        VALUES(SecurityMapping[Region]),
        SecurityMapping[UserEmail] = CurrentUser
            || SecurityMapping[UserEmail] = "ALL"
    )
RETURN
    [Region] IN UserRegions

这种方法避免了额外关系的复杂性并保持安全逻辑的独立性。

具有管理器层次结构的动态 RLS

一个常见的要求是管理者可以查看整个报告链的数据。这需要员工或用户表中的父子层次结构。

方法一:PATH函数

如果您的用户表有 ManagerId 列,请使用 DAX 的 PATH 函数:

UserPath = PATH(Users[UserId], Users[ManagerId])

那么在RLS表达式中:

VAR CurrentUserId =
    LOOKUPVALUE(Users[UserId], Users[Email], USERPRINCIPALNAME())
RETURN
    PATHCONTAINS([UserPath], CurrentUserId)

对于当前用户自己的数据以及属于其直接和间接报告的所有数据,此表达式返回 TRUE。

方法 2:扁平化安全表

预先计算 ETL 流程中的层次结构并创建平面安全映射,其中列出每个经理及其所有报告的数据范围。这在查询时性能更高,因为它避免了 PATH 评估的开销。


对象级安全性 (OLS)

对象级安全性向用户隐藏整个表或列。与过滤行的 RLS 不同,OLS 使表或列完全不可见——它们不会出现在字段列表中,并且任何引用隐藏字段的视觉效果都会显示错误。

何时使用 OLS

  • 对非 HR 用户隐藏 HR 数据集中的薪资列
  • 对只应看到收入的销售团队隐藏与成本相关的表格
  • 对只需要汇总数据的分析师隐藏客户 PII(电子邮件、电话、地址)
  • 对一般用户隐藏战略定价列

配置 OLS

OLS 通过表格编辑器(外部工具)或 XMLA 终结点进行配置,而不是通过 Power BI Desktop UI。

在表格编辑器中:

1.通过外部工具功能区打开模型 2. 导航到要限制的表或列 3. 在属性窗格中,找到每个角色下的表权限或列权限 4.将权限设置为“无”(默认为“读取”)

例如,要对“销售”角色隐藏员工表中的薪资列:

  • 角色:销售
  • 表:员工
  • 栏目:薪资
  • 权限:无

分配了销售角色的用户将看不到字段列表中的“薪资”列,也无法在 DAX 计算中引用它。

OLS 限制

  • OLS 需要启用 XMLA 端点的 Power BI Premium 或 Pro
  • 无法在 Power BI Desktop 的本机 UI 中配置 OLS
  • OLS 仅是元数据级别 --- 它不过滤行
  • 如果某个度量引用了隐藏列,则该度量本身将对受限用户出错

RLS 与 DirectQuery

RLS 可与 DirectQuery 配合使用,但其行为在重要方面与导入模式不同。

它是如何运作的

在 DirectQuery 模式下,Power BI 将 RLS DAX 筛选器转换为 SQL WHERE 子句并将其发送到数据源。数据源执行过滤,仅返回授权行。

单点登录 (SSO) 传递

将 DirectQuery 与 SSO 结合使用到 Azure SQL 或 Azure Synapse 等数据库时,Power BI 会将用户的身份传递到数据库。如果数据库有自己的行级安全性(例如 SQL Server 的 CREATE SECURITY POLICY),则除了 Power BI 的 RLS 之外,该安全性也适用。

重要提示: 如果启用 SSO 传递,Power BI 的 RLS 将被绕过,因为数据库会处理安全性。您必须选择其中之一:

  • Power BI RLS(在 DAX 中定义,在 Power BI 中管理)
  • 数据库级RLS(在SQL中定义,在数据库中管理)
  • 两者(Power BI RLS 和数据库 RLS 应用 --- 用户看到交集)

性能考虑因素

DirectQuery 中的 RLS 筛选器向每个查询添加 WHERE 子句。如果过滤器列未在数据库中建立索引,性能可能会显着降低。确保:

  • RLS过滤列有数据库索引
  • DAX 过滤表达式足够简单,可以转换为高效的 SQL
  • 使用 Power BI Desktop 中的“性能分析器”测试查询性能

Power BI Embedded 中的 RLS

Power BI Embedded(在自定义应用程序中嵌入报表)具有独特的 RLS 要求,因为最终用户可能没有 Power BI 或 Azure AD 帐户。

应用程序拥有数据场景

在“应用程序拥有数据”嵌入模式中,服务主体或主帐户向 Power BI 进行身份验证,并且应用程序在嵌入令牌中传递用户身份。

使用 RLS 生成嵌入令牌:

调用 Power BI REST API 生成嵌入令牌时,请包含 identities 参数:

{
  "datasets": [
    {
      "id": "dataset-guid-here"
    }
  ],
  "reports": [
    {
      "id": "report-guid-here"
    }
  ],
  "identities": [
    {
      "username": "[email protected]",
      "roles": ["DynamicSecurity"],
      "datasets": ["dataset-guid-here"]
    }
  ]
}

username 值是 USERPRINCIPALNAME() 在 DAX 表达式中返回的值。 roles 数组指定要应用的 RLS 角色。您可以传递任何字符串作为用户名 --- 它不需要是真正的 Azure AD 帐户。

常见嵌入错误

错误 1:未传递有效身份。 如果生成不带 identities 参数的嵌入令牌,嵌入报告将显示所有数据。这是最常见的 RLS 嵌入错误。

错误 2:传递角色但不传递用户名。 动态 RLS 需要用户名。如果没有它,USERPRINCIPALNAME() 将返回空白,并且 DAX 过滤器不会匹配任何行 --- 报表显示为空。

错误 3:使用服务主体的身份。 服务主体是工作区管理员并绕过 RLS。您必须显式传递最终用户的身份。

错误 4:在动态 RLS 的嵌入令牌中对角色进行硬编码。 如果您将动态 RLS 与单个角色(例如“DynamicSecurity”)一起使用,请始终传递该角色名称。不要为每个用户创建单独的角色 --- 这违背了动态 RLS 的目的。


测试行级安全性

查看角色 (Power BI Desktop)

在 Power BI Desktop 中,转到“建模”,然后“查看为”:

  1. 选择要测试的角色
  2. (可选)输入用户名来测试动态 RLS(这会模拟 USERPRINCIPALNAME() 值)
  3. 单击“确定”

该报告现在显示数据,就好像您是具有指定角色的指定用户一样。验证:

  • KPI 卡显示正确的过滤总计
  • 表格仅显示用户范围内的行
  • 图表反映过滤后的数据
  • 视觉效果之间的交叉过滤尊重 RLS 边界
  • 钻取页面维护 RLS 上下文

查看方式(Power BI 服务)

在 Power BI 服务中,打开数据集设置并选择安全性。您可以通过选择“测试角色”并输入用户名来直接测试角色。

自动化测试清单

创建包含以下场景的测试矩阵:

测试用例预期结果
具有单一角色的用户仅查看其地区/部门/公司数据
具有多个角色的用户查看所有分配角色数据的并集
未分配角色的用户没有看到任何数据(报告为空)
具有 ALL/全局访问权限的用户查看所有数据
具有层级访问权限的经理查看自己的数据以及所有直接/间接报告
新维度增值验证新值是否对适当的用户可见
导出到 Excel导出的数据遵循 RLS 过滤器
订阅电子邮件电子邮件包含经过 RLS 过滤的数据
自然语言问答答案尊重 RLS 过滤器
移动应用程序RLS 适用于移动视图

RLS 性能优化

衡量影响

在实施 RLS 之前和之后,使用 Power BI Desktop 中的性能分析器来测量查询时间。打开性能分析器窗格,开始记录,与报告交互,并比较使用和不使用 RLS 的 DAX 查询时间。

设计良好的 RLS 实施增加的开销不到 5%。如果您发现性能下降超过 10%,请调查 DAX 筛选器表达式。

优化技术

保持过滤表达式简单。 理想的 RLS 表达式是单列比较:

[Region] = USERPRINCIPALNAME()

避免在 RLS 过滤器本身中使用多个 CALCULATE、FILTER 或 LOOKUPVALUE 调用来实现复杂表达式。

使用整数键而不是文本比较。[CompanyId] = 1 进行过滤比 [CompanyName] = "ECOSIRE Private Limited" 更快。将用户电子邮件映射到安全映射表中的整数键。

使用 RLS 过滤器最小化表的数量。 将 RLS 应用于维度表并让关系传播处理事实表。将 RLS 直接应用于大型事实表会强制 Power BI 对事实表的每一行评估筛选器。

尽可能进行预聚合。 如果用户只需要摘要级别的数据,请考虑创建一个预聚合表,并在 ETL 期间应用安全过滤器。这减少了 Power BI 在查询时需要筛选的数据量。

**避免双向交叉过滤器。**双向关系会增加查询复杂性并可能与 RLS 发生冲突。使用单向关系(从维度到事实)并在维度侧应用 RLS。


常见陷阱和解决方案

陷阱 1:RLS 不适用于工作区管理员

具有编辑权限的工作区管理员和成员绕过 RLS。他们总是看到所有数据。这是设计使然——管理员需要完全访问权限才能管理工作区。

解决方案: 对应受 RLS 约束的业务用户使用“查看者”角色。仅向 BI 团队授予管理员/成员/贡献者角色。

陷阱 2:ALL() 删除 RLS 过滤器

DAX ALL() 函数从表中删除所有筛选器,包括 RLS 筛选器。如果度量在经过 RLS 过滤的表上使用 ALL(),则可能会暴露用户不应看到的数据。

-- DANGEROUS: This measure ignores RLS on Dim_Region
Total Global Sales =
CALCULATE(SUM(Fact_Sales[Revenue]), ALL(Dim_Region))

解决方案: 当您想要删除切片器/视觉过滤器但保留 RLS 过滤器时,请使用 ALLSELECTED() 而不是 ALL():

-- SAFE: This measure preserves RLS filters
Total Sales for Context =
CALCULATE(SUM(Fact_Sales[Revenue]), ALLSELECTED(Dim_Region))

陷阱 3:计算覆盖 RLS

在某些情况下,使用显式过滤器参数的 CALCULATE 可以覆盖 RLS,特别是使用 REMOVEFILTERS:

-- DANGEROUS: REMOVEFILTERS is equivalent to ALL
Total Revenue All Regions =
CALCULATE(SUM(Fact_Sales[Revenue]), REMOVEFILTERS(Dim_Region[Region]))

解决方案: 审核 ALL、REMOVEFILTERS 和 ALLEXCEPT 使用情况的所有 DAX 度量。确保它们不引用 RLS 过滤列。

陷阱 4:复合模型和 RLS

在复合模型(混合导入和 DirectQuery)中,必须为导入表和 DirectQuery 表单独定义 RLS。单个 RLS 角色可以包含两者的过滤器,但行为不同:

  • 导入表:RLS 过滤器由 Power BI 引擎评估
  • DirectQuery 表:RLS 过滤器转换为 SQL 并发送到源

如果 DirectQuery 源不支持 RLS 筛选器中使用的 DAX 函数,查询将失败。

陷阱 5:分页报告忽略 RLS

如果 Power BI 分页报表(在报表生成器中创建)直接连接到数据源,则可以绕过数据集 RLS。要强制实施 RLS,分页报表必须通过 Power BI 数据集连接(而不是直接连接到数据库),并且用户必须具有分配的 RLS 角色。


企业RLS架构模式

对于大型组织,ECOSIRE 建议 标准化 RLS 架构:

安全层设计

  1. 安全映射表 存储在中央数据库中(Azure SQL 或 SharePoint 列表)
  2. 单个 RLS 角色 使用 USERPRINCIPALNAME() 命名为“DynamicSecurity”
  3. Azure AD 组同步 根据组成员身份自动填充安全映射表
  4. 使用预展平父子表的层次结构支持
  5. 审核跟踪 记录哪些用户访问了哪些数据(通过 Power BI 活动日志和 REST API)

治理流程

  1. 数据管理员维护安全映射表
  2. 通过变更管理流程审核和批准变更
  3. 每月审核将 Power BI RLS 分配与 HR 记录系统进行比较
  4. 每季度渗透测试验证 RLS 有效性

该架构可扩展到数百个数据集的数千个用户,同时保持单点安全管理。


常见问题解答

RLS 是否可以与 Power BI 免费许可证一起使用?

不需要。对于使用 RLS 保护的报表的所有用户,RLS 需要 Power BI Pro 或 Premium Per User 许可证。免费许可证用户只能访问高级容量工作区中的内容,即使如此,他们也需要 Pro 或 PPU 许可证才能分配 RLS 角色。在 Power BI Embedded 场景中,最终用户不需要 Power BI 许可证 --- RLS 通过嵌入令牌强制执行。

我可以基于 Azure AD 组而不是个人用户实施 RLS 吗?

不直接。 Power BI 的 RLS 根据 USERPRINCIPALNAME() 评估 DAX 表达式,该表达式返回单个用户的电子邮件。但是,您可以创建一个安全映射表,将 Azure AD 组映射到数据范围,并使用 Microsoft Graph API 或 Azure AD 组成员身份同步来填充该表。 DAX 表达式仍然按用户的电子邮件进行过滤,但安全映射表提供组到数据的映射。

如果用户未分配任何 RLS 角色,会发生什么情况?

如果在数据集上定义 RLS 并且用户未分配任何角色,则用户看不到任何数据。报告已加载,但所有视觉效果均显示空白或零。这是安全默认设置 --- Power BI 假定没有访问权限,除非明确授予。但是,具有“编辑”权限的工作区管理员和成员可以绕过 RLS,并且始终可以查看所有数据,无论角色分配如何。

RLS可以过滤实时仪表板中的数据吗?

是的。 RLS 适用于导入和 DirectQuery 模式。在 DirectQuery 模式下,RLS 筛选器会转换为 SQL WHERE 子句,并随每个查询一起发送到数据库,因此筛选是实时发生的。在导入模式下,当用户打开报表时,过滤将在内存中应用。两种模式提供相同的安全保证——用户只能看到授权的数据。

如何审核谁通过 RLS 访问了哪些数据?

Power BI 通过 Microsoft 365 管理中心和 Power BI REST API 提供活动日志。这些日志记录报告视图、数据集刷新和导出操作,包括用户的身份。但是,日志不会记录用户查看了哪些特定行。对于详细的数据访问审核,请启用数据库级审核(例如 PostgreSQL pgaudit 或 Azure SQL 审核)以记录应用了 RLS 筛选器的 DirectQuery 生成的实际查询。

E

作者

ECOSIRE Research and Development Team

在 ECOSIRE 构建企业级数字产品。分享关于 Odoo 集成、电商自动化和 AI 驱动商业解决方案的洞见。

通过 WhatsApp 聊天