SSAS中CUBE行权限数据级权限控制

时间:2022-04-29 19:43:17

去年做了一个数据仓库的项目,其中涉及到了CUBE数据级权限的控制。在网上找这方面的资料,找到一个[BI] 通用数据级权限控制解决方案的实现(二):Cube中的角色设置与数据级权限控制。根据这个大牛的思路,做完之后发现有几个问题:

1. 传递给CUBE的用户必须是域用户或者数据库服务器WINDOWS用户。如果BI系统不是用的AD域认证而是传统的FORM认证,那么,BI里的用户需要对应一个WINDOWS用户。

2. 另外的WEB程序里保存对cube的角色权限之后,用户访问cube数据的权限控制并不能即时刷新,需要到SSAS数据库里手动保存一下角色,权限配置才能够生效。

首先添加一个SSAS的角色Role,注意角色的数据库权限设置不能勾选完全控制,不然后面我们配置的权限就没有任何意义。在成员身份为角色添加用户和组,按前面帖子里说的添加everyone,其实后面按照我的方法,这里不需要添加everyone,只需要添加一个最大权限的用户即可。如图一(还是添加的everyone)

SSAS中CUBE行权限数据级权限控制

                  图一

在左侧数据源及多维数据集的选项中需要给数据源及多维数据集读的权限。

在维度数据里选择需要设置权限的维度及维度属性,我这里的是一个父子级的维度,成本中心,选择成本中心层次结构。如图二,

SSAS中CUBE行权限数据级权限控制

                  图二

在允许的成员集里,我写的字符串如下

StrToSet(BII.GetCubeDimPerMems(CustomData(),"WEGODW","成本中心"))

其中,还是使用MDX的函数StrToSet来将我们自己写的DLL查询出的维度成员列表转换成MDX能够识别的Member Set。

GetCubeDimPerMems函数是我自己写的一个查询某个用户在数据库中保存的能够访问的某个维度的成员列表的字符串。第一个参数也是这个方法的核心,需要用到MDX的一个函数CustomData()。

CustomData(MDX)

如果已定义,则返回 CustomData 连接字符串属性的值;否则,返回 null。

返回值:CustomData 函数可以检索 CustomData 连接字符串属性并传递多维表达式 (MDX) 函数和语句将要使用的配置设置,例如,UserName (MDX) 和 CALL 语句 (MDX)。 例如,该函数可以用在动态安全表达式中,用于在 CustomData 连接字符串属性中选择允许的集成员或拒绝的集成员。

这里第二个和第三个参数没啥意义,我这里表示是我CUBENAME以及DIMNAME,大家可以自己随意发挥。

查询结果大致格式如下:

"[成本中心].[成本中心层次].&[1],[成本中心].[成本中心层次].&[2],[成本中心].[成本中心层次].&[3],[成本中心].[成本中心层次].&[4]"

那我们如何将我们WEB程序里的程序传递给SSAS呢?我这边使用了WEB.CONFIG里的connectingstring的方式,用连接字符串的方式将用户传递给SSAS,使之能够知道是哪个用户连接并打开了数据库。连接字符串如下:

string connectionString = "Provider=MSOLAP.5;Data Source=http://172.0.0.1:8088/OLAP/msmdpump.dll; Persist Security Info=true;Password=xxxxx;User ID=administrator;CustomData=UserName;initial catalog=DBName;Cube Name=CubeName;Roles=Role;"

其中,User ID是我们需要连接SSAS库的最大权限的用户(管理员账户),相当于SQL SERVER里的SA账户。Roles=role必须强制进行角色认证,不然当以administrator用户连接SSAS时,会取得完全控制权限。

重点就是CustomData属性,将我们WEB程序里的用户名,通过CustomData传递给SSAS,在SSAS里用MDX函数CustomData()来接收。比如我在connectionString里定义CustomData=zhangsan,在SSAS里通过CustomData()就能够得到”zhangsan“这个用户。

这里还有一点需要注意,SSAS数据库必须以HTTP的方式发布到IIS,这样才能够远程访问。

补充一点,关于将用户权限设置更新之后,CUBE权限不能及时刷新的问题,这个其实是SQL SERVSER的一个BUG,貌似到2014版本还未得到解决。解决方法为更新下CUBE的ROLE。代码如下

Server ser = new Server();
ser.Connect(connectString_cube);
Database db = ser.Databases.FindByName(DbName);
Role _role = db.Roles[0];
_role.Update();

在设置用户维度数据访问权限之后,更新ROLE即可。 

混了这么久园子,第一次写东西,算是对自己做过东西的一点总结,班门弄斧,还望各位前辈多多指教。