在個人不少Winform開發項目中(包括混合框架的項目),統一採用了權限管理模塊來進行各類權限的控制,包括常規的功能權限(按鈕、菜單權限)、數據權限(記錄的權限),另外還能夠進行字段級別的字段權限控制,字段權限是咱們在一些對權限要求比較嚴格的系統裏面涉及到的,能夠對部分用戶隱藏一些敏感的信息。本篇主要介紹字段權限的控制思路及實現機制,以便你們對這個字段權限的控制有一個直觀的瞭解。html
若是須要對權限系統的功能進行必定的瞭解,能夠先回顧下我前面的文章《Winform開發框架之權限管理系統功能介紹》、《如何在應用系統中實現數據權限的控制功能》、《如何在應用系統中實現數據權限的控制功能(2)》,以及《Winform開發框架之權限管理系統改進的經驗總結(1)-TreeListLookupEdit控件的使用》、《Winform開發框架之權限管理系統改進的經驗總結(2)-用戶選擇界面的設計》、《Winform開發框架之權限管理系統改進的經驗總結(4)--用戶分級管理》等文章。框架
字段的權限控制,通常就是控制對應角色人員的對某個表的一些敏感字段的可訪問性:包括可見、可編輯性等處理。ide
在設計字段權限的時候,咱們須要瞭解這些仍是基於RBAC的概念,基於角色進行受權的,並且咱們的字段列表是屬於具體的業務對象列表的,這裏的業務對象是指一些咱們具體的業務模塊,如客戶基礎信息、人員基礎信息、報價單等等,咱們就是基於這些業務進行字段的控制的。函數
以下界面所示,咱們在權限系統裏面也能夠對其字段進行權限控制,以下圖所示。先選擇左邊的具體角色,而後添加一些業務對象,並設置它們的權限便可。工具
首次業務對象須要用戶加入,這裏以程序集中的實體類進行字段信息的標識處理,以下所示能夠加載對應業務信息。post
咱們在業務對象列表的【顯示設置】處能夠單擊旁邊的按鈕,在彈出的界面上進行條件的設置,以下界面效果所示。this
這樣咱們就完成了對某個業務對象的各個字段進行配置了,具體的字段控制在業務模塊裏面添加部分代碼便可實現了。url
例如咱們以系統黑名單爲例介紹,經過上面的方式進行設置,隱藏起始和結束IP地址的字段,那麼列表界面獲得的效果以下所示。spa
同時,若是系統界面有新增或者編輯界面,那麼咱們也須要隱藏才能夠達到效果,以下是其的編輯界面效果(隱藏顯示那兩個字段了)。設計
以上就是整個字段權限控制的設計思路和實現了,可是具體咱們是如何在業務模塊裏面整合這些權限控制呢?下面咱們進行介紹。
前面咱們介紹了在權限系統中進行業務對象的字段權限的設置流程,以及以其中的【登錄系統黑白名單】的業務模塊進行的演示,那麼咱們如何才能在本身的業務模塊裏面進行控制處理的呢?
首先咱們須要在業務列表綁定的時候,須要獲取咱們當前用戶可以訪問的字段列表,默認是所有可見,可是若是用戶設置了條件,那麼就須要獲取對應的權限列表進行控制了,具體的控制代碼以下所示。
//根據業務對象獲取對應的顯示字段,若是沒有設置,那麼根據FieldPermit表的配置獲取字段權限列表 var permitDict = BLLFactory<FieldPermit>.Instance.GetColumnsPermit(typeof(BlackIPInfo).FullName, Portal.gc.UserInfo.ID); var displayColumns = BLLFactory<BlackIP>.Instance.GetDisplayColumns(); displayColumns = string.IsNullOrEmpty(displayColumns) ? string.Join(",", permitDict.Keys) : displayColumns; this.winGridViewPager1.DisplayColumns = displayColumns;
而後在設置字段的中文映射顯示
//設置字段的中文顯示 this.winGridViewPager1.ColumnNameAlias = BLLFactory<BlackIP>.Instance.GetColumnNameAlias();//字段列顯示名稱轉義
在對列表進行數據綁定後,咱們統一設置各個字段的權限的可讀寫、可見或隱藏值權限便可,以下代碼所示。
//獲取字段顯示權限,並設置 this.winGridViewPager1.gridView1.SetColumnsPermit(permitDict);
整個數據綁定的代碼以下所示,這些代碼能夠利用代碼生成工具Database2Sharp進行界面代碼統一輩子成。
/// <summary> /// 綁定列表數據 /// </summary> private void BindData() { //entity //根據業務對象獲取對應的顯示字段,若是沒有設置,那麼根據FieldPermit表的配置獲取字段權限列表 var permitDict = BLLFactory<FieldPermit>.Instance.GetColumnsPermit(typeof(BlackIPInfo).FullName, Portal.gc.UserInfo.ID); var displayColumns = BLLFactory<BlackIP>.Instance.GetDisplayColumns(); displayColumns = string.IsNullOrEmpty(displayColumns) ? string.Join(",", permitDict.Keys) : displayColumns; this.winGridViewPager1.DisplayColumns = displayColumns; //設置字段的中文顯示 this.winGridViewPager1.ColumnNameAlias = BLLFactory<BlackIP>.Instance.GetColumnNameAlias();//字段列顯示名稱轉義 string where = GetConditionSql(); List<BlackIPInfo> list = BLLFactory<BlackIP>.Instance.Find(where); this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<BlackIPInfo>(list); this.winGridViewPager1.PrintTitle = "登錄系統的黑白名單列表報表"; //獲取字段顯示權限,並設置 this.winGridViewPager1.gridView1.SetColumnsPermit(permitDict); }
對於DevExpress的GridControl列表控件,咱們通常在處理過程當中須要設置字段的DisplayText轉義,那麼這種設置後,經過上面代碼處理的權限就會失效,咱們能夠利用對Tag的標識的判斷進行處理,以下所示,這樣就避免了權限控制無效的狀況。
void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) { //若是字段權限不夠,那麼字段的標籤設置爲*的 if (string.Concat(e.Column.Tag) != "*") { if (e.Column.ColumnType == typeof(DateTime)) { string columnName = e.Column.FieldName; if (e.Value != null) { if (Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1")) { e.DisplayText = ""; } else { e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm");//yyyy-MM-dd } } } else if (e.Column.FieldName == "AuthorizeType") { if (e.Value != null) { e.DisplayText = ((AuthrizeType)e.Value).ToString(); } } } }
若是在開發Winform界面的時候,把列表的展現統一放在GridControl裏面進行展現,再也不獨立設計展現窗體,那麼上面列表控制就已經達到了字段權限的控制目的了:可見或不可見、可編輯或只讀、顯示或隱藏值等處理。
在個人Winform框架中,我通常傾向於設計一個界面來展現業務對象的內容,通常新增,查看或者編輯都放在這個窗體上展現信息,比較直觀,那麼這種對字段權限的控制也須要延伸到這個顯示窗體上;
對於普通的編輯控件,咱們只能控制控件的可讀寫、可見與否的處理。
首先咱們設計一個函數,用來設置控件的權限的,以下所示。
/// <summary> /// 設置控件字段的權限顯示或者隱藏 /// </summary> private void SetPermit() { #region 設置控件和字段的對應關係 this.txtName.Tag = "Name"; this.txtAuthorizeType.Tag = "AuthorizeType"; this.txtForbid.Tag = "Forbid"; this.txtIPStart.Tag = "IPStart"; this.txtIPEnd.Tag = "IPEnd"; this.txtNote.Tag = "Note"; this.txtCreator.Tag = "Creator"; this.txtCreateTime.Tag = "CreateTime"; #endregion //獲取列表權限的列表 var permitDict = CallerFactory<IFieldPermitService>.Instance.GetColumnsPermit(typeof(BlackIPInfo).FullName, Portal.gc.UserInfo.ID); this.SetControlPermit(permitDict, this.layoutControl1); }
在上面,咱們的邏輯就是先爲每一個控件綁定一個字段的標識,最後經過獲取用戶的字段權限列表,對控件的權限進行統一的控制處理便可。
爲了開發的省時省力,這些代碼能夠利用代碼生成工具Database2Sharp進行界面代碼統一輩子成。
完成上面SetPermit函數的處理,咱們在窗體界面的顯示內容上,最後統一設置控件的權限便可,以下代碼所示。
/// <summary> /// 數據顯示的函數 /// </summary> public override void DisplayData() { InitDictItem();//數據字典加載(公用) if (!string.IsNullOrEmpty(ID)) { #region 顯示信息 BlackIPInfo info = CallerFactory<IBlackIPService>.Instance.FindByID(ID); if (info != null) { tempInfo = info;//從新給臨時對象賦值,使之指向存在的記錄對象 txtName.Text = info.Name; txtAuthorizeType.SetComboBoxItem(info.AuthorizeType.ToString()); txtForbid.Checked = info.Forbid; txtIPStart.Text = info.IPStart; txtIPEnd.Text = info.IPEnd; txtNote.Text = info.Note; txtCreator.Text = info.Creator; txtCreateTime.SetDateTime(info.CreateTime); } #endregion //this.btnOK.Enabled = Portal.gc.HasFunction("BlackIP/Edit"); } else { txtCreator.Text = Portal.gc.UserInfo.FullName;//默認爲當前登陸用戶 txtCreateTime.DateTime = DateTime.Now; //默認當前時間 //this.btnOK.Enabled = Portal.gc.HasFunction("BlackIP/Add"); } RefreshUsers(); SetPermit(); }
以上就是字段權限的設計思路,實現控制過程,這樣咱們在權限裏面實現了功能權限、菜單權限、數據記錄權限、字段權限的綜合控制,基本上可以知足大多數業務規則的要求了,從而提升了權限管理系統在整個應用開發中的通用性、便利性,一致性。