轉載地址:http://www.cnblogs.com/leoxie2011/archive/2012/03/20/2408542.html html
前一篇文章《通用權限管理設計 之 數據庫設計方案》介紹了【主體】- 【領域】 - 【權限】( who、what、how問題原型 ) 的設計思想數據庫設計
本文將對這種設計思想做進一步的擴展,介紹數據權限的設計方案。ui
權限控制能夠理解,分爲這幾種 :
【功能權限】:能作什麼的問題,如增長產品。
【數據權限】:能看到哪些數據的問題,如查看本人的全部訂單。
【字段權限】:能看到哪些信息的問題,如供應商帳戶,看不到角色、 部門等信息。
上面提到的那種設計就是【功能權限】,這種設計有必定的侷限性,對於主體,只能明確地指定。對於不明確的,在這裏可能就沒辦法處理。好比下面這幾種狀況:
數據僅當前部門及上級可見
數據僅當前用戶(本人)可見
相似這樣的就須要用到上面提的數據權限。
上一篇文章我用一個表五個字段完成了【功能權限】的設計思路
本文我將介紹如何利用一個表兩個字段完成這個【數據權限】的設計思路
【數據權限】是在【功能權限】的基礎上面進一步的擴展,好比能夠查看訂單屬於【功能權限】的範圍,可是能夠查看哪些訂單就是【數據權限】的工做了。
在設計中,咱們規定好若是沒有設置了數據權限規則,那麼視爲容許查看所有的數據。
幾個概念
【資源】:數據權限的控制對象,業務系統中的各類資源。好比訂單單據、銷售單等。屬於上面提到的【領域】中的一種
【主體】:用戶、部門、角色等。
【條件規則】:用於檢索數據的條件定義
【數據規則】:用於【數據權限】的條件規則
應用場景
1,訂單,能夠由本人查看
2,銷售單,能夠由本人或上級領導查看
3,銷售單,銷售人員能夠查看本身的,銷售經理只查看 銷售金額大於100,000的。
咱們能想到直接的方法,在訪問數據的入口加入SQL Where條件來實現,組織sql語句:
, UserID {CurrentUserID} , UserID {CurrentUserID} {CurrentUserID} (領導) , UserID {CurrentUserID} ({CurrentUserID} (銷售經理) 銷售金額 )
這些一個一個的"條件",本文簡單理解爲一個【數據規則】,一般會與原來咱們前臺的業務過濾條件合併再檢索出數據。
這是一種最直接的實現方式,在【資源】上面加一個【數據規則】(好比上面的三點)。這樣設計就是
【資源】 - 【數據規則】
我又以爲不一樣的人應該對應不一樣的規則,那麼也能夠理解爲,一個用戶對應不一樣的角色,每個角色有不同的【數據規則】,那麼設計就變成
【資源】 - 【主體】 - 【數據規則】
根據提供者的不一樣,準備不一樣的權限應對策略。
這裏能夠簡單地介紹一下,這個方案至少須要2張表,一個是 【資源,主體,規則關係表】、一個是【數據規則表】
關係表不能直接保存角色,由於你不肯定何時業務須要按照【部門】或者【分公司】來定義數據規則
因而能夠用 Master、MasterKey 相似這樣的兩個字段來肯定一個【主體】
用XML方式的話是這樣配置的(放在數據庫也相似):
銷售員 = {CurrentUserID} 銷售金額 > 100000 銷售金額 > 100000 and 區域 = {當前用戶所屬區域}
對於這種方式有興趣的朋友也能夠試一下,兩種方式的【數據規則】是同樣的,可是本文沒有采用第二種設計方式,由於它多了一層處理邏輯,我覺得應該設計越簡單越好,就採用第一種方式:
【資源】 - 【數據規則】
固然,上面是用SQL的方式來肯定條件規則的,咱們固然不會這麼作。SQL雖然靈活,可是咱們很難去維護,也不知道SQL在咱們的界面UI上面如何體現。難不成直接用一個文本框來顯示。這樣對應一個開發人員來講不是問題,但是對應系統管理員,很容易出問題。因此咱們須要有另外一方式來肯定這一規則,並最終能夠轉換成咱們的SQL語句。
咱們的設計關鍵在於如何規範好這些【數據規則】 ,這個規則必須是對前端友好的,並且是對後臺友好的,JSON顯然是很好的方式。
規則說明:
1,數據權限規則老是:{屬性 條件 容許值}
2,數據權限規則能夠合併。好比 ( {當前用戶 屬於 銷售人員} and {訂單銷售員 等於 當前用戶} ) Or {當前用戶 屬於 銷售經理}
3,最終咱們會用JSON格式
在檢索數據時會先判斷有沒有註冊了某某【資源】的【條件規則】,若是有,那麼加載這個【條件規則】併合併到咱們前臺的【搜索條件】(你的業務界面應該有一個搜索框吧)
以下圖定義了客戶信息的搜索框,咱們搜索客戶ID包括AN,咱們組織成的規則將會是:
{"rules":[{"field":"CustomerID","op":"like","value":"AN","type":"string"}],"op":"and"}
爲了更好地理解【數據規則】,這裏介紹一下【通用查詢機制】
權限控制總離不開一些條件的限制(好比查看當前部門的單據),若是沒有完善的通用查詢規則機制,那麼在作權限條件過濾的時候你會以爲很彆扭。這裏介紹一個通用查詢方案,而後再介紹如何實現【數據規則】。
早些時候我寫過一篇關於ligerGrid結合.net設計通用處理類的文章《 jQuery liger ui ligerGrid 打造通用的分頁排序查詢表格(提供下載) 》。裏面提到的過濾信息是直接的SQL語句。這是不可靠,並且不安全的。
在前端傳輸給後臺的過濾信息不該該是直接的SQL,而應該是一組過濾規則。在ligerui V1.1.8 已經加入了一個條件過濾器插件,這個插件組成的規則數據纔是我受推薦的:
好比以下
{"rules":
[
{"field":"OrderDate","op":"less","value":"2012-01-01"},
{"field":"CustomerID","op":"equal","value":"VINET"}
]
,"op":"and"}
規則描述:
查找顧客VINET全部訂單時間小於2011-01-01的單據
這樣的數據是安全的,並且是通用的(你甚至能夠再加一個OR子查詢)。不管是在前端仍是後臺,不管你使用什麼樣的組件,均可以很好地利用。
通用後臺的翻譯,就能夠生成這樣SQL的參數:
: ( ) Parameters: p1: p2:VINET
下面來點複雜的:查找 顧客VINET或者TOMSP,全部訂單時間小於2011-01-01的單據
{
"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"
}
翻譯結果:
:( ( )) Parameters: p1: p2:VINET p3:TOMSP
這個過濾規則分爲三個部分:【分組】、【規則】(字段、值、操做符)、【操做符】(and or),而自身就是一個分組。
這種簡單的結構就能夠知足所有的狀況。
固然,上面提到的這些條件都是在前臺定義(多是用戶在搜索框本身輸入的)的,而在後臺,咱們可能會定義一下【隱藏條件】,好比說 【員工只能查看本身的】,要怎麼作呢,其實很簡單,只須要在後臺接收到這個過濾條件(前臺toJSON,後臺解析JSON)之後,再加上一個過濾規則(隱藏條件):
{field:'EmployeeID',op:'equal',value:5}
能夠將原來的過濾規則當作一個分組加入進行:
{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: p2: p3:VINET p4:TOMSP
這樣的【條件規則】纔是咱們想要的,不只在前端能夠很好地解析,也能夠在後臺進行處理。在後臺咱們會定義跟這種數據結構對應的類,那麼再定義一個翻譯成SQL的類:
說了這些,能夠開始介紹如何實現【數據規則】了:
上面提到的【隱藏條件】,就是我介紹的【數據規則】
試想一些,這樣 前臺的過濾規則,再加上咱們之間定義好的 【數據權限】控制 過濾條件。不就達到目的了嗎。
先看看咱們在數據庫裏保存的這些【數據規則】:
看不明白?那來個清楚一點的:
規則描述
訂單:【訂單管理員和演示角色能夠查看全部的】,【訂單查看員】只能查看本身的
產品:【基礎信息錄入員和演示角色能夠查看全部的】,【供應商】只能查看本身的
{CurrentEmployeeID}表示當前的員工。
實質上,咱們還能夠根據當前用戶信息定義須要的參數,好比:
{CurrentUserID} 當前用戶Id ,對應表【CF_User】
{CurrentRoleID} 當前角色Id ,對應表 【CF_Role】
{CurrentDeptID} 當前用戶部門Id,對應表【CF_Department】
{CurrentEmployeeID} 當前用戶員工Id,對應表【Employees】(CF_User.EmployeeID)
{CurrentSupplierID} 當前用戶供應商Id,對應表【Suppliers】(CF_User.SupplierID)
在數據庫中咱們直接保存這些用戶參數,在「翻譯」規則成爲SQL時,會替換掉:
好比查看訂單,咱們獲得的SQL,多是這樣的:
: ( ( ( (( (,)) ( ))) OrderID ) tmptableinner OrderID ) tmptableouter OrderID Parameters:
{CurrentRuleID} 替換爲 7
{CurrentEmployeeID} 替換爲1
下圖是咱們設計【數據權限】的界面,能夠選擇全部的字段,包括幾個用戶信息:
這些字段不只僅只是在文本框中輸入值,那麼能夠自定義數據來源:
fieldEditors {}; fieldEditors { : { type: , options: { width: , url: "..handler.ashx?OrdersidfieldShipCitytextfieldShipCitytrue" } } };
效果界面:
既然是數據權限控制,若是有一個統一的數據接收入口,咱們卻是能夠利用這個入口作一些工做。
好比【ligerRM權限管理系統】統一使用 grid.ashx 這個數據處理程序做爲列表數據的接收入口。
有了統一的接口,方便作權限的控制,使用過 ligerGrid Javascript表格,或者相似插件的朋友,應該比較清楚服務器的交互原理。
在grid.ashx中,咱們會經過
【視圖/表名 】、 【排序信息】、【分頁信息】、【過濾信息】
這幾個指標來獲取指定的數據。
而在實際的業務中,可能會引入權限的控制。好比某某【資源】,只能由當前用戶自身才能查看,或者只能由當前用戶部門及上級部門才能查看。對於這些控制,咱們採用對這些可能作權限控制的【資源】註冊一組【條件規則】的方式來進行。
咱們將找到view定義好的【數據權限規則】,而後和用戶在前臺搜索框輸入的【搜索規則】合併:
上面的代碼就是數據條件合併的例子,這樣便獲得了咱們最終須要的 過濾規則。