通用權(quán)限管理設(shè)計(jì) 之 數(shù)據(jù)權(quán)限
本文關(guān)鍵詞:權(quán)限管理,由筆耕文化傳播整理發(fā)布。
閱讀目錄
前言
前一篇文章《通用權(quán)限管理設(shè)計(jì) 之 數(shù)據(jù)庫設(shè)計(jì)方案》介紹了【主體】- 【領(lǐng)域】 - 【權(quán)限】( who、what、how問題原型 ) 的設(shè)計(jì)思想
本文將對(duì)這種設(shè)計(jì)思想作進(jìn)一步的擴(kuò)展,介紹數(shù)據(jù)權(quán)限的設(shè)計(jì)方案。
權(quán)限控制可以理解,分為這幾種 :
【功能權(quán)限】:能做什么的問題,如增加產(chǎn)品。
【數(shù)據(jù)權(quán)限】:能看到哪些數(shù)據(jù)的問題,如查看本人的所有訂單。
【字段權(quán)限】:能看到哪些信息的問題,如供應(yīng)商賬戶,看不到角色、 部門等信息。
上面提到的那種設(shè)計(jì)就是【功能權(quán)限】,這種設(shè)計(jì)有一定的局限性,對(duì)于主體,只能明確地指定。對(duì)于不明確的,在這里可能就沒辦法處理。比如下面這幾種情況:
數(shù)據(jù)僅當(dāng)前部門及上級(jí)可見
數(shù)據(jù)僅當(dāng)前用戶(本人)可見
類似這樣的就需要用到上面提的數(shù)據(jù)權(quán)限。
上一篇文章我用一個(gè)表五個(gè)字段完成了【功能權(quán)限】的設(shè)計(jì)思路
本文我將介紹如何利用一個(gè)表兩個(gè)字段完成這個(gè)【數(shù)據(jù)權(quán)限】的設(shè)計(jì)思路
【數(shù)據(jù)權(quán)限】是在【功能權(quán)限】的基礎(chǔ)上面進(jìn)一步的擴(kuò)展,比如可以查看訂單屬于【功能權(quán)限】的范圍,但是可以查看哪些訂單就是【數(shù)據(jù)權(quán)限】的工作了。
在設(shè)計(jì)中,我們規(guī)定好如果沒有設(shè)置了數(shù)據(jù)權(quán)限規(guī)則,那么視為允許查看全部的數(shù)據(jù)。
幾個(gè)概念
【資源】:數(shù)據(jù)權(quán)限的控制對(duì)象,業(yè)務(wù)系統(tǒng)中的各種資源。比如訂單單據(jù)、銷售單等。屬于上面提到的【領(lǐng)域】中的一種
【主體】:用戶、部門、角色等。
【條件規(guī)則】:用于檢索數(shù)據(jù)的條件定義
【數(shù)據(jù)規(guī)則】:用于【數(shù)據(jù)權(quán)限】的條件規(guī)則
應(yīng)用場(chǎng)景
1,訂單,可以由本人查看
2,銷售單,可以由本人或上級(jí)領(lǐng)導(dǎo)查看
3,銷售單,銷售人員可以查看自己的,銷售經(jīng)理只查看 銷售金額大于100,000的。
我們能想到直接的方法,在訪問數(shù)據(jù)的入口加入SQL Where條件來實(shí)現(xiàn),組織sql語句:
1,where UserID = {CurrentUserID}
2,where UserID = {CurrentUserID} or {CurrentUserID} in (領(lǐng)導(dǎo))
3,where UserID = {CurrentUserID} or ({CurrentUserID} in (銷售經(jīng)理) and 銷售金額 > 100000)
這些一個(gè)一個(gè)的"條件",本文簡(jiǎn)單理解為一個(gè)【數(shù)據(jù)規(guī)則】,通常會(huì)與原來我們前臺(tái)的業(yè)務(wù)過濾條件合并再檢索出數(shù)據(jù)。
這是一種最直接的實(shí)現(xiàn)方式,在【資源】上面加一個(gè)【數(shù)據(jù)規(guī)則】(比如上面的三點(diǎn))。這樣設(shè)計(jì)就是
【資源】 - 【數(shù)據(jù)規(guī)則】
我又覺得不同的人應(yīng)該對(duì)應(yīng)不同的規(guī)則,那么也可以理解為,一個(gè)用戶對(duì)應(yīng)不同的角色,每一個(gè)角色有不一樣的【數(shù)據(jù)規(guī)則】,那么設(shè)計(jì)就變成
【資源】 - 【主體】 - 【數(shù)據(jù)規(guī)則】
根據(jù)提供者的不同,準(zhǔn)備不同的權(quán)限應(yīng)對(duì)策略。
這里可以簡(jiǎn)單地介紹一下,這個(gè)方案至少需要2張表,一個(gè)是 【資源,主體,規(guī)則關(guān)系表】、一個(gè)是【數(shù)據(jù)規(guī)則表】
關(guān)系表不能直接保存角色,因?yàn)槟悴淮_定什么時(shí)候業(yè)務(wù)需要按照【部門】或者【分公司】來定義數(shù)據(jù)規(guī)則
于是可以用 Master、MasterKey 類似這樣的兩個(gè)字段來確定一個(gè)【主體】
用XML方式的話是這樣配置的(放在數(shù)據(jù)庫也類似):
銷售員 = {CurrentUserID}
銷售金額 > 100000
銷售金額 > 100000 and 區(qū)域 = {當(dāng)前用戶所屬區(qū)域}
【資源】 - 【數(shù)據(jù)規(guī)則】
當(dāng)然,上面是用SQL的方式來確定條件規(guī)則的,我們當(dāng)然不會(huì)這么做。SQL雖然靈活,但是我們很難去維護(hù),也不知道SQL在我們的界面UI上面如何體現(xiàn)。難不成直接用一個(gè)文本框來顯示。這樣對(duì)應(yīng)一個(gè)開發(fā)人員來說不是問題,可是對(duì)應(yīng)系統(tǒng)管理員,很容易出問題。所以我們需要有另一方式來確定這一規(guī)則,并最終可以轉(zhuǎn)換成我們的SQL語句。
我們的設(shè)計(jì)關(guān)鍵在于如何規(guī)范好這些【數(shù)據(jù)規(guī)則】 ,這個(gè)規(guī)則必須是對(duì)前端友好的,而且是對(duì)后臺(tái)友好的,JSON顯然是很好的方式。
規(guī)則說明:
1,數(shù)據(jù)權(quán)限規(guī)則總是:{屬性 條件 允許值}
2,數(shù)據(jù)權(quán)限規(guī)則可以合并。比如 ( {當(dāng)前用戶 屬于 銷售人員} and {訂單銷售員 等于 當(dāng)前用戶} ) Or {當(dāng)前用戶 屬于 銷售經(jīng)理}
3,最終我們會(huì)用JSON格式
在檢索數(shù)據(jù)時(shí)會(huì)先判斷有沒有注冊(cè)了某某【資源】的【條件規(guī)則】,如果有,那么加載這個(gè)【條件規(guī)則】并合并到我們前臺(tái)的【搜索條件】(你的業(yè)務(wù)界面應(yīng)該有一個(gè)搜索框吧)
如下圖定義了客戶信息的搜索框,我們搜索客戶ID包括AN,我們組織成的規(guī)則將會(huì)是:
{"rules":[{"field":"CustomerID","op":"like","value":"AN","type":"string"}],"op":"and"}
為了更好地理解【數(shù)據(jù)規(guī)則】,這里介紹一下【通用查詢機(jī)制】
【通用查詢機(jī)制】權(quán)限控制總離不開一些條件的限制(比如查看當(dāng)前部門的單據(jù)),如果沒有完善的通用查詢規(guī)則機(jī)制,那么在做權(quán)限條件過濾的時(shí)候你會(huì)覺得很別扭。這里介紹一個(gè)通用查詢方案,然后再介紹如何實(shí)現(xiàn)【數(shù)據(jù)規(guī)則】。
早些時(shí)候我寫過一篇關(guān)于ligerGrid結(jié)合.net設(shè)計(jì)通用處理類的文章《 jQuery liger ui ligerGrid 打造通用的分頁排序查詢表格(提供下載) 》。里面提到的過濾信息是直接的SQL語句。這是不可靠,而且不安全的。
在前端傳輸給后臺(tái)的過濾信息不應(yīng)該是直接的SQL,,而應(yīng)該是一組過濾規(guī)則。在ligerui V1.1.8 已經(jīng)加入了一個(gè)條件過濾器插件,這個(gè)插件組成的規(guī)則數(shù)據(jù)才是我受推薦的:
比如如下
{"rules":
[
{"field":"OrderDate","op":"less","value":"2012-01-01"},
{"field":"CustomerID","op":"equal","value":"VINET"}
]
,"op":"and"}
規(guī)則描述:
查找顧客VINET所有訂單時(shí)間小于2011-01-01的單據(jù)
這樣的數(shù)據(jù)是安全的,而且是通用的(你甚至可以再加一個(gè)OR子查詢)。無論是在前端還是后臺(tái),無論你使用什么樣的組件,都可以很好地利用。
通用后臺(tái)的翻譯,就可以生成這樣SQL的參數(shù):
)
Parameters:
p1:
p2:VINET
下面來點(diǎn)復(fù)雜的:查找 顧客VINET或者TOMSP,所有訂單時(shí)間小于2011-01-01的單據(jù)
{
"rules":[{"field":"OrderDate","op":"less","value":"2012-01-01"}],
"groups":[
{"rules":[{"field":"CustomerID","op":"equal","value":"VINET"}, {"field":"CustomerID","op":"equal","value":"TOMSP"}],"op":"or"}
],
"op":"and"
}
翻譯結(jié)果:
())
Parameters:
p1:
p2:VINET
p3:TOMSP
這個(gè)過濾規(guī)則分為三個(gè)部分:【分組】、【規(guī)則】(字段、值、操作符)、【操作符】(and or),而自身就是一個(gè)分組。
這種簡(jiǎn)單的結(jié)構(gòu)就可以滿足全部的情況。
當(dāng)然,上面提到的這些條件都是在前臺(tái)定義(可能是用戶在搜索框自己輸入的)的,而在后臺(tái),我們可能會(huì)定義一下【隱藏條件】,比如說 【員工只能查看自己的】,要怎么做呢,其實(shí)很簡(jiǎn)單,只需要在后臺(tái)接收到這個(gè)過濾條件(前臺(tái)toJSON,后臺(tái)解析JSON)以后,再加上一個(gè)過濾規(guī)則(隱藏條件):
{field:'EmployeeID',op:'equal',value:5}
可以將原來的過濾規(guī)則當(dāng)做一個(gè)分組加入進(jìn)行:
{op:'and',groups:[
{"rules":[{"field":"OrderDate","op":"less","value":"2012-01-01"}],
"groups":[
{"rules":[{"field":"CustomerID","op":"equal","value":"VINET"},{"field":"CustomerID","op":"equal","value":"TOMSP"}],"op":"or"}
],"op":"and"}
],rules:[{field:'EmployeeID',op:'equal',value:5}]
}
翻譯如下:
(()))
Parameters:
p1:
p3:VINET
p4:TOMSP
這樣的【條件規(guī)則】才是我們想要的,不僅在前端可以很好地解析,也可以在后臺(tái)進(jìn)行處理。在后臺(tái)我們會(huì)定義跟這種數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的類,那么再定義一個(gè)翻譯成SQL的類:
說了這些,可以開始介紹如何實(shí)現(xiàn)【數(shù)據(jù)規(guī)則】了:
上面提到的【隱藏條件】,就是我介紹的【數(shù)據(jù)規(guī)則】
試想一些,這樣 前臺(tái)的過濾規(guī)則,再加上我們之間定義好的 【數(shù)據(jù)權(quán)限】控制 過濾條件。不就達(dá)到目的了嗎。
先看看我們?cè)跀?shù)據(jù)庫里保存的這些【數(shù)據(jù)規(guī)則】:
看不明白?那來個(gè)清楚一點(diǎn)的:
規(guī)則描述
訂單:【訂單管理員和演示角色可以查看所有的】,【訂單查看員】只能查看自己的
產(chǎn)品:【基礎(chǔ)信息錄入員和演示角色可以查看所有的】,【供應(yīng)商】只能查看自己的
{CurrentEmployeeID}表示當(dāng)前的員工。
實(shí)質(zhì)上,我們還可以根據(jù)當(dāng)前用戶信息定義需要的參數(shù),比如:
{CurrentUserID} 當(dāng)前用戶Id ,對(duì)應(yīng)表【CF_User】
{CurrentRoleID} 當(dāng)前角色I(xiàn)d ,對(duì)應(yīng)表 【CF_Role】
{CurrentDeptID} 當(dāng)前用戶部門Id,對(duì)應(yīng)表【CF_Department】
{CurrentEmployeeID} 當(dāng)前用戶員工Id,對(duì)應(yīng)表【Employees】(CF_User.EmployeeID)
{CurrentSupplierID} 當(dāng)前用戶供應(yīng)商Id,對(duì)應(yīng)表【Suppliers】(CF_User.SupplierID)
在數(shù)據(jù)庫中我們直接保存這些用戶參數(shù),在“翻譯”規(guī)則成為SQL時(shí),會(huì)替換掉:
比如查看訂單,我們得到的SQL,可能是這樣的:
((( (())) OrderID
{CurrentRuleID} 替換為 7
{CurrentEmployeeID} 替換為1
下圖是我們?cè)O(shè)計(jì)【數(shù)據(jù)權(quán)限】的界面,可以選擇所有的字段,包括幾個(gè)用戶信息:
這些字段不僅僅只是在文本框中輸入值,那么可以自定義數(shù)據(jù)來源:
{
: { type: ,
options: {
width: Orderstrue"
}
}
};
效果界面:
既然是數(shù)據(jù)權(quán)限控制,如果有一個(gè)統(tǒng)一的數(shù)據(jù)接收入口,我們倒是可以利用這個(gè)入口做一些工作。
比如【ligerRM權(quán)限管理系統(tǒng)】統(tǒng)一使用 grid.ashx 這個(gè)數(shù)據(jù)處理程序作為列表數(shù)據(jù)的接收入口。
有了統(tǒng)一的接口,方便做權(quán)限的控制,使用過 ligerGrid Javascript表格,或者類似插件的朋友,應(yīng)該比較清楚服務(wù)器的交互原理。
在grid.ashx中,我們會(huì)通過
【視圖/表名 】、 【排序信息】、【分頁信息】、【過濾信息】
這幾個(gè)指標(biāo)來獲取指定的數(shù)據(jù)。
而在實(shí)際的業(yè)務(wù)中,可能會(huì)引入權(quán)限的控制。比如某某【資源】,只能由當(dāng)前用戶自身才能查看,或者只能由當(dāng)前用戶部門及上級(jí)部門才能查看。對(duì)于這些控制,我們采用對(duì)這些可能做權(quán)限控制的【資源】注冊(cè)一組【條件規(guī)則】的方式來進(jìn)行。
我們將找到view定義好的【數(shù)據(jù)權(quán)限規(guī)則】,然后和用戶在前臺(tái)搜索框輸入的【搜索規(guī)則】合并:
上面的代碼就是數(shù)據(jù)條件合并的例子,這樣便得到了我們最終需要的 過濾規(guī)則。
結(jié)語本文提出了數(shù)據(jù)權(quán)限的一種實(shí)現(xiàn)思路,只是本人在做一個(gè)web應(yīng)用時(shí)構(gòu)思的方案,談不上規(guī)范,歡迎提出你的建議意見。
可以在體驗(yàn)實(shí)際的應(yīng)用效果。
本文關(guān)鍵詞:權(quán)限管理,由筆耕文化傳播整理發(fā)布。
本文編號(hào):45007
本文鏈接:http://sikaile.net/wenshubaike/jjyglkx/45007.html