问题描述
我正在尝试实现一种在SSAS表格导入上使用动态数据屏蔽的方法。默认情况下,据我所知,SQL Server Analysis Services 2016不支持此功能。我想我已经找到了一种使用动态行级安全性来实现此目的的方法。但是,我的结果与预期不符。
我的案例是一个Employee表。它包含大约2000行,我的测试用户被授权查看大约50行。 我已经导入了Employee表,添加了一个Security表(EmployeeKey,Username),并在Employee表上设置了行过滤器。与the sample from Microsoft大致相同。
此外,我还添加了一个名为EmployeeMask的表,该表包含相同的2000行,相同的EmployeeKeys和相同的列。但是,我已经“掩盖”了其余列的值。
使用模拟为我的测试用户的MDX查询,我从Employee表中检索了50名雇员,从EmployeeMask表中检索了2000名雇员。到现在为止还挺好。现在是我认为自己很聪明的部分。我重命名了Employee表EmployeeAuthorized并添加了一个计算表Employee,如下所示:
=UNION(
EmployeeAuthorized;
FILTER(
EmployeeMask;
LOOKUPVALUE(EmployeeAuthorized[EmployeeKey]; EmployeeAuthorized[EmployeeKey]; EmployeeMask[EmployeeKey])
= BLANK()
)
)
但是,对我的新计算表Employee使用MDX查询,我得到了所有2000行未屏蔽的信息。我的猜测是,已计算的表会事先得到处理,而我认为DAX公式将根据请求执行。我的猜测对吗?有什么方法可以满足我的要求吗?
样本数据:
CREATE TABLE [dbo].[Employee] (--Renamed this to EmployeeAuthorized
[EmployeeKey] INT NOT NULL,[EmployeeName] VARCHAR(50) NOT NULL
);
INSERT INTO [dbo].[Employee] VALUES
(1,'A A'),(2,'B B'),(3,'C C');
CREATE TABLE [dbo].[Fact] (
[EmployeeKey] INT NOT NULL,[Value] INT NOT NULL
);
INSERT INTO [dbo].[Fact] VALUES
(1,1),2),5),8);
CREATE TABLE [dbo].[Security] (
[EmployeeKey] INT NOT NULL,[UserName] VARCHAR(50) NOT NULL
);
INSERT INTO [dbo].[Security] VALUES
(1,'domain\u1'),(1,'domain\u2');
如果需要的话:
CREATE TABLE [dbo].[EmployeeMask] (
[EmployeeKey] INT NOT NULL,[EmployeeName] VARCHAR(50) NOT NULL
);
INSERT INTO [dbo].[EmployeeMask] VALUES
(1,'masked'),'masked');
我正在尝试完成以下任务:
解决方法
-
Ditch
上UNION
会忽略过滤器上下文和您的RLS。使用LOOKUPVALUE
来确保用户有权访问EmployeeMasked
上的行,具体取决于他们的EmployeeKey
是否存在于EmployeeAuthorized
-
编辑您的
返回的ADUsername值。EmployeeAuthorized
表,使其包含一个ADUsername
列。对于每个EmployeeKey,存储将从dax函数USERNAME()
-
编辑您创建的角色,然后转到行过滤器标签。
-
查找EmployeeMask表
-
添加以下DAX筛选器,以便角色强制实施属于该角色的用户,如果其EmployeeKey / ADUsername在EmployeeAuthorizedy中具有相应的查找授权记录,则只能看到EmployeeMask上的行。
=EmployeeMask[EmployeeKey]
=LOOKUPVALUE(
EmployeeAuthorizedy[EmployeeKey],EmployeeAuthorized[EmployeeKey],EmployeeMask[EmployeeKey],EmployeeAuthorized[ADUsername],USERNAME()
)
,
我能够如下解决这个难题:
我将表导入到SSAS表格模型中。我两次导入了表Employee,一次作为Employee,一次作为EmployeeKey,只有列EmployeeKey。
如您所见,关系如下:
Fact[EmployeeKey] *:1 (<< To Fact) EmployeeKey[EmployeeKey]
Employee[EmployeeKey] *:1 (<< To Both Tables >>) EmployeeKey[EmployeeKey]
Security[EmployeeKey] *:1 (<< To Security) Employee[EmployeeKey]
我添加了具有读取权限和以下行过滤器的单个角色:
Table Employee: =Employee[EmployeeKey]=LOOKUPVALUE(Security[EmployeeKey]; Security[UserName]; USERNAME(); Security[EmployeeKey]; Employee[EmployeeKey])
Table Security: =FALSE()
结果: