去年做了一個數據倉庫的項目,其中涉及到了CUBE數據級權限的控制。在網上找這方面的資料,找到一個[BI] 通用數據級權限控制解決方案的實現(二):Cube中的角色設置與數據級權限控制。根據這個大牛的思路,做完之后發現有幾個問題:
1. 傳遞給CUBE的用戶必須是域用戶或者數據庫服務器WINDOWS用戶。如果BI系統不是用的AD域認證而是傳統的FORM認證,那么,BI里的用戶需要對應一個WINDOWS用戶。
2. 另外的WEB程序里保存對cube的角色權限之后,用戶訪問cube數據的權限控制並不能即時刷新,需要到SSAS數據庫里手動保存一下角色,權限配置才能夠生效。
首先添加一個SSAS的角色Role,注意角色的數據庫權限設置不能勾選完全控制,不然后面我們配置的權限就沒有任何意義。在成員身份為角色添加用戶和組,按前面帖子里說的添加everyone,其實后面按照我的方法,這里不需要添加everyone,只需要添加一個最大權限的用戶即可。如圖一(還是添加的everyone)
圖一
在左側數據源及多維數據集的選項中需要給數據源及多維數據集讀的權限。
在維度數據里選擇需要設置權限的維度及維度屬性,我這里的是一個父子級的維度,成本中心,選擇成本中心層次結構。如圖二,
圖二
在允許的成員集里,我寫的字符串如下
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即可。
混了這么久園子,第一次寫東西,算是對自己做過東西的一點總結,班門弄斧,還望各位前輩多多指教。