關(guān)于數(shù)據(jù)權(quán)限的控制湘捎,可能我們在做很多大型一點的系統(tǒng)都會碰到過阎抒,可能每個人設(shè)計和解決問題的思路都有所不同,本文介紹我自己框架里面的解決思路消痛。從上一篇《如何在應(yīng)用系統(tǒng)中實現(xiàn)數(shù)據(jù)權(quán)限的控制功能》里面我們可能對權(quán)限控制和數(shù)據(jù)權(quán)限的控制有了一個初步的了解,本文接著進一步介紹在應(yīng)用系統(tǒng)中都哭,如何集成數(shù)據(jù)權(quán)限的控制功能秩伞。
1、數(shù)據(jù)權(quán)限實現(xiàn)思路分析
為了實現(xiàn)數(shù)據(jù)權(quán)限的控制欺矫,我們需要在通用的權(quán)限系統(tǒng)里面保存好對應(yīng)角色具有哪些組織機構(gòu)的數(shù)據(jù)權(quán)限纱新,然后在應(yīng)用系統(tǒng)中調(diào)用API進行過濾數(shù)據(jù)處理即可。
為了實現(xiàn)以上的功能需求脸爱,我們需要在權(quán)限系統(tǒng)里面,角色控制哪里增加一個數(shù)據(jù)權(quán)限的數(shù)據(jù)存儲未妹。
實際的應(yīng)用系統(tǒng)簿废,當用戶登陸成功后,我們獲取并記錄好其可以管理的公司或者部門络它,如果是主管的角色族檬,可能有多個公司的數(shù)據(jù)可以管理,那么可以在程序的頂部化戳,讓用戶選擇管理那個公司的數(shù)據(jù)即可单料,如果切換公司,那么刷新現(xiàn)有的界面數(shù)據(jù)顯示就可以了。
在用戶成功登陸后扫尖,我們可以記錄用戶的相關(guān)權(quán)限控制信息白对,如他所能控制數(shù)據(jù)的公司或者部門,把它記錄下來换怖。
Portal.gc.CompanyList = BLLFactory<RoleData>.Instance.GetBelongCompanysByUser(info.ID);
List<int> deptList = BLLFactory<RoleData>.Instance.GetBelongDeptsByUser(info.ID);
Portal.gc.DeptList = deptList;
然后存儲用戶默認的公司ID甩恼,并根據(jù)用戶是否為管理員(超級管理員、公司管理員)狰域,然后構(gòu)造一個通用的過濾條件媳拴,放到全局緩存里面,方便各個模塊使用兆览,如下代碼所示铐炫。
//設(shè)置選定的公司ID(默認為用戶所在公司的ID)
Cache.Instance["SelectedCompanyID"] = info.Company_ID;
//設(shè)置過濾條件給界面基類使用
string filterCondition = string.Format(" Company_ID = '{0}' ", info.Company_ID);
if (!Portal.gc.IsAdmin)
{
if (deptList.Count > 0)
{
filterCondition += string.Format(" AND Dept_ID IN ({0})", string.Join(",", deptList));
}
else
{
filterCondition += string.Format(" AND Creator = '{0}' ", info.ID);
}
}
Cache.Instance["DataFilterCondition"] = filterCondition;
在主界面的時候典奉,我們可以根據(jù)用戶所能管理的公司數(shù)據(jù),在頂部初始化公司列表,方便切換選擇模狭,以下是初始化的代碼。
//添加受管理的公司機構(gòu)
//判斷如果用戶管理的公司數(shù)據(jù)多于一個玉工,那么就顯示選擇單位列表缚俏,并綁定公司數(shù)據(jù)
if (Portal.gc.CompanyList.Count > 1)
{
this.repositoryCompanyItem.Items.Clear();
foreach (int company in Portal.gc.CompanyList)
{
OUInfo companyInfo = BLLFactory<OU>.Instance.FindByID(company);
if (companyInfo != null)
{
this.repositoryCompanyItem.Items.Add(new CListItem(companyInfo.Name, companyInfo.ID.ToString()));
}
}
//多于一個顯示公司下拉列表
this.barCompanyItem.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
}
else
{
//只有一個公司時候,屏蔽公司選擇列表
this.barCompanyItem.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
}
如果多于一個公司怠益,那么正常的需求是可以切換公司來查看其它公司的數(shù)據(jù)的仪搔,要實現(xiàn)這個功能,那么就需要修改登陸的那個全局的過濾條件:Cache.Instance["DataFilterCondition"]了蜻牢。
我們來看看代碼的實現(xiàn)烤咧,其主要的邏輯就是獲取用戶選擇的公司ID,然后根據(jù)公司抢呆、部門信息煮嫌,重新構(gòu)建一個全局的過濾條件,并重新緩存到對應(yīng)的鍵值里面去抱虐,供后面的窗體實現(xiàn)數(shù)據(jù)的過濾更新昌阿。
CListItem item = this.barCompanyItem.EditValue as CListItem;
if (item != null)
{
//設(shè)置選定的公司ID
Cache.Instance["SelectedCompanyID"] = item.Value;
SetSelectedCompanyName();
//設(shè)置過濾條件給界面基類使用
string filterCondition = string.Format(" Company_ID = '{0}' ", item.Value);
if (!Portal.gc.IsAdmin)
{
if (Portal.gc.DeptList.Count > 0)
{
filterCondition += string.Format(" AND Dept_ID IN ({0})", string.Join(",", Portal.gc.DeptList));
}
else
{
filterCondition += string.Format(" AND Creator = '{0}' ", Portal.gc.UserInfo.ID);
}
}
Cache.Instance["DataFilterCondition"] = filterCondition;
如果需要對已有的窗體實現(xiàn)數(shù)據(jù)更新,那么遍歷窗體恳邀,并統(tǒng)一實現(xiàn)數(shù)據(jù)刷新即可懦冰。
//遍歷全部窗口,更新
foreach (WHC.Framework.BaseUI.BaseDock form in this.MdiChildren)
{
form.SelectedCompanyID = item.Value;
form.DataFilterCondition = filterCondition;
form.FormOnLoad();
}
string message = string.Format("您已經(jīng)切換數(shù)據(jù)顯示:{0}", item.Text);
MessageDxUtil.ShowTips(message);
2谣沸、窗體數(shù)據(jù)過濾的實現(xiàn)
從上面的步驟代碼儿奶,我們可以看到如何構(gòu)建一個全局的過濾條件,但是我們獲取數(shù)據(jù)的時候鳄抒,如何才能實現(xiàn)數(shù)據(jù)權(quán)限的控制闯捎,讓用戶所能看到的數(shù)據(jù)在可控的范圍內(nèi)呢椰弊?
我們知道,一般窗體數(shù)據(jù)列表的綁定操作類似如下代碼所示
/// <summary>
/// 綁定列表數(shù)據(jù)
/// </summary>
private void BindData()
{
//entity
this.winGridViewPager1.DisplayColumns = displayColumns;
this.winGridViewPager1.ColumnNameAlias = CallerFactory<ICustomerService>.Instance.GetColumnNameAlias();//字段列顯示名稱轉(zhuǎn)義
string where = GetConditionSql();
PagerInfo pagerInfo = this.winGridViewPager1.PagerInfo;
List<CustomerInfo> list = CallerFactory<ICustomerService>.Instance.FindWithPager(where, ref pagerInfo);
this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<CustomerInfo>(list);
this.winGridViewPager1.PrintTitle = "客戶信息列表";
}
所以主要的數(shù)據(jù)控制瓤鼻,就在函數(shù)GetConditionSql()里面了秉版,那么這個里面,我們?nèi)绾握锨懊娴倪^濾條件呢茬祷?
下面是一個案例代碼清焕。
/// <summary>
/// 根據(jù)查詢條件構(gòu)造查詢語句
/// </summary>
private string GetConditionSql()
{
//如果存在高級查詢對象信息,則使用高級查詢條件祭犯,否則使用主表條件查詢
SearchCondition condition = advanceCondition;
if (condition == null)
{
condition = new SearchCondition();
if(customGridLookUpEdit1.EditValue != null)
{
condition.AddCondition("ID", customGridLookUpEdit1.EditValue.ToString(), SqlOperator.Equal);
}
condition.AddCondition("Deleted", 0, SqlOperator.Equal);//不顯示刪除的
}
string where = condition.BuildConditionSql().Replace("Where", "");
//如果是單擊節(jié)點得到的條件秸妥,則使用樹列表的,否則使用查詢條件的
if (!string.IsNullOrEmpty(treeConditionSql))
{
where = treeConditionSql + " AND Deleted = 0 ";//不顯示刪除的
}
//數(shù)據(jù)權(quán)限的過濾:過濾規(guī)則沃粗,如果指定公司粥惧,以公司過濾,如果進一步指定部門最盅,以公司+部門進行過濾突雪;否則以個人的數(shù)據(jù)展示
//如果過濾條件不為空,那么需要進行過濾
if (!string.IsNullOrEmpty(this.DataFilterCondition))
{
where += string.Format(" AND {0}", this.DataFilterCondition);
}
return where;
}
我們主要關(guān)注下上面紅色部分即可涡贱,因為我們已經(jīng)加上了標準的過濾條件了咏删,這樣我們就可以看到自己管理的數(shù)據(jù)了。
為了實現(xiàn)統(tǒng)一的數(shù)據(jù)控制问词,我們要求整個業(yè)務(wù)表的設(shè)計督函,需要引入下面幾個標準的字段,這樣就能很好使用過濾條件進行數(shù)據(jù)的過濾了激挪。
前面也介紹到了侨核,窗體可以統(tǒng)一刷新,其奧秘就是它們遵循統(tǒng)一的一個數(shù)據(jù)加載接口灌灾,我們初始化窗體數(shù)據(jù)的函數(shù)代碼如下所示。
/// <summary>
/// 編寫初始化窗體的實現(xiàn)悲柱,可以用于刷新
/// </summary>
public override void FormOnLoad()
{
InitDictItem();
BindData();
InitCustomerPage();
}
所以它們就能夠統(tǒng)一調(diào)用FormOnLoad來統(tǒng)一刷新數(shù)據(jù)锋喜,就是這個道理。
//遍歷全部窗口豌鸡,更新
foreach (WHC.Framework.BaseUI.BaseDock form in this.MdiChildren)
{
form.SelectedCompanyID = item.Value;
form.DataFilterCondition = filterCondition;
form.FormOnLoad();
}
以上就是我對數(shù)據(jù)權(quán)限控制的一些心得和實現(xiàn)思路嘿般,希望大家能夠體會其中的思路,并批判性的提出意見和建議涯冠。