close
關於權限設計的探討    
   
   
  但凡涉及多用戶不同權限的網絡或者單機程序,都會有權限管理的問題,比較突出的是MIS系統。    
   
  下面我要說的是MIS系統權限管理的數據庫設計及實現,當然,這些思路也可以推廣開來應用,比如說在BBS中用來管理不同級別的用戶權限。    
   
  權限設計通常包括數據庫設計、應用程序接口(API)設計、程序實現三個部分。    
   
  這三個部分相互依存,密不可分,要實現完善的權限管理體系,必須考慮到每一個環節可行性與複雜程度甚至執行效率。    
   
  我們將權限分類,首先是針對數據存取的權限,通常有錄入、瀏覽、修改、刪除四種,其次是功能,它可以包括例如統計等所有非直接數據存取操作,另外,我們還可能對一些關鍵數據表某些字段的存取進行限制。除此,我想不出還有另外種類的權限類別。    
   
  完善的權限設計應該具有充分的可擴展性,也就是說,系統增加了新的其它功能不應該對整個權限管理體繫帶來較大的變化,要達到這個目的,首先是數據庫設計合理,其次是應用程序接口規範。    
   
  我們先討論數據庫設計。通常我們使用關係數據庫,這裡不討論基於Lotus產品的權限管理。    
   
  權限表及相關內容大體可以用六個表來描述,如下:    
  1   角色(即用戶組)表:包括三個字段,ID,角色名,對該角色的描述;    
  2   用戶表:包括三個或以上字段,ID,用戶名,對該用戶的描述,其它(如地址、電話等信息);    
  3   角色-用戶對應表:該表記錄用戶與角色之間的對應關係,一個用戶可以隸屬於多個角色,一個角色組也可擁有多個用戶。包括三個字段,ID,角色ID,用戶ID;    
  4   限制內容列表:該表記錄所有需要加以權限區分限制的數據表、功能和字段等內容及其描述,包括三個字段,ID,名稱,描述;    
  5   權限列表:該表記錄所有要加以控制的權限,如錄入、修改、刪除、執行等,也包括三個字段,ID,名稱,描述;    
  6   權限-角色-用戶對應表:一般情況下,我們對角色/用戶所擁有的權限做如下規定,角色擁有明令允許的權限,其它一律禁止,用戶繼承所屬角色的全部權限,在此範圍內的權限除明令禁止外全部允許,範圍外權限除明令允許外全部禁止。該表的設計是權限管理的重點,設計的思路也很多,可以說各有千秋,不能生搬硬套說某種方法好。對此,我的看法是就個人情況,找自己覺得合適能解決問題的用。    
   
  先說第一種也是最容易理解的方法,設計五個字段:ID,限制內容ID,權限ID,角色/用戶類型(布爾型字段,用來描述一條記錄記錄的是角色權限還是用戶權限),角色/用戶ID,權限類型(布爾型字段,用來描述一條記錄表示允許還是禁止)    
   
  好了,有這六個表,根據表六,我們就可以知道某個角色/用戶到底擁有/禁止某種權限。    
   
  或者說,這麼設計已經足夠了,我們完全實現了所需要的功能:可以對角色和用戶分別進行權限定制,也具有相當的可擴展性,比如說增加了新功能,我們只需要添加一條或者幾條記錄就可以,同時應用程序接口也無須改動,具有相當的可行性。但是,在程序實現的過程中,我們發現,使用這種方法並不是十分科學,例如瀏覽某個用戶所擁有的權限時,需要對數據庫進行多次(甚至是遞歸)查詢,極不方便。於是我們需要想其它的辦法。使用過Unix系統的人們都知道,Unix文件系統將對文件的操作權限分為三種:讀、寫和執行,分別用1、2、4三個代碼標識,對用戶同時具有讀寫權限的文件被記錄為3,即1+2。我們也可以用類似的辦法來解決這個問題。初步的想法是修改權限列表,加入一個字段:標識碼,例如,我們可以將錄入權限標識為1,瀏覽權限標識為2,修改權限標識為4,刪除權限標識為8,執行權限標識為16,這樣,我們通過權限累加的辦法就可以輕易的將原本要分為幾條記錄描述的權限放在一起了,例如,假定某用戶ID為1,庫存表對應的限制內容ID為2,同時規定角色類型為0、用戶類型為1,我們就可以將該用戶具有錄入、瀏覽、修改、刪除庫存表的權限描述為:2,15,1,1。    
   
  確實很簡單,不是嗎?甚至還有更過激的辦法,將限制內容列表也加上一列,定義好標識碼,這樣,我們甚至可以用簡單的一條記錄描述某個用戶具有的對全部內容所具有的全部權限了。當然,這樣做的前提是限制內容數量比較小,不然,呵呵,2的n次方遞增起來可是數量驚人,不容易解析的。    
   
  從表面上看,上述方法足以達到實現功能、簡化數據庫設計及實現的複雜度這個目的,但這樣做有個弊端,我們所涉及的權限列表不是相互獨立而是互相依賴的,比如說修改權限,其實是包含瀏覽權限的,例如,我們可能只是簡單的設置用戶對庫存表存取的權限值為錄入+修改+刪除(1+4+8=13),但事實上,該用戶具有(1+2+4+8=15)的權限,也就是說,在這種方案中,13=15。於是當我們調用API詢問某用戶是否具有瀏覽權限時,就必須判斷該用戶是否具有對該數據表的修改權限,因此,如果不能在程序中固化權限之間的包含關係,就不能利用應用程序接口簡單的做出判斷。但這與我們的目的「充分的可擴展性」矛盾。    
   
  這個問題如何解決?我想到了另外一種設置標識碼的方法,那就是利用素數。我們不妨將錄入、瀏覽、修改、刪除、執行的基本標誌碼定為2,3,5,7,11,當遇到權限互相包含的時候,我們將它的標識碼設定為兩個(或多個)基本標誌碼的乘積,例如,可以將「修改」功能的標誌碼定為3*5=15,然後將所有的權限相乘,就得到了我們需要的最終權限標識值。這樣,我們在詢問用戶是否具有某項權限的時候,只需要將最終的值分解成質因子,例如,我們可以定義一個用戶具有錄入+修改+刪除庫存表的權限為   2*15*7=2*3*5*7,即表示,該用戶具有了對庫存表錄入+瀏覽+修改+刪除權限。    
   
  當然,對權限列表我們使用上述方法的前提是權限列表記錄條數不會太多並且關係不是十分複雜,否則,光是解析權限代碼就要機器忽悠半宿:)    
   
  我希望以上的分析是正確且有效的(事實上,我也用這些的方法在不止一套系統中實現),但無論如何,我覺得如此實現權限管理,只是考慮了數據庫設計和應用程序接口兩部分內容,對於實現,還是顯得很費勁。因此,我懇請有過類似設計、實現經驗的同志們提出建設性的意見和修改建議。  
arrow
arrow
    全站熱搜

    icejuly 發表在 痞客邦 留言(0) 人氣()