我設計的權限管理方案

這是給我們學校的某管理系統設計的一套權限管理子系統。今天把它總結一下,歡迎大牛過來踩。

權限系統的設計對於企業級項目來說極爲重要,尤其是像我們的系統,數據很重要,要是成績被人修改了,那就糟糕了。

其實權限控制無非是兩方面:控制合適的人訪問到合適的菜單,進入合適的菜單項之後可以訪問到合適的數據。

我把系統設計的儘量簡化,主要牽涉到以下幾個對象。

一個是權限所有者Accessor,即訪問者

      Accessor可以使一個用戶,也可以是一個角色或是崗位,是什麼只有客戶程序知道。

 

一個是資源,Resource,表示可被訪問的數據,

     爲樹形結構,每個資源爲一個樹的節點。客戶程序可以自己控制資源的粒度。

 

一個是功能模塊,Module,一個功能模塊,或者是一個可訪問的頁面。

     由於這部分有其他人員開發,我的程序裏面沒有涉及到這個類,只是引用了這個類的ID。

 

一個是權限Authoritied,有三個外鍵,分別指向上面三個對象,其實就是一張三表關聯的中間表。

 

針對以上所述,對程序敏感的你可能會提出以下問題:

1. Accessor可以是一個用戶,也可以是一個角色或是崗位,那麼如何表示一個訪問者呢?

    我用了AccessorName這個字段,它是一個字符串類型,而且是不可重複的,由於我們的系統裏表都有uuid,所以就把uuid放進來,作爲AccessorName了。這裏有一點,客戶程序不只需用告訴我訪問者的AccessorName是什麼,並不需要知道這個Accessor是什麼類型,所以這裏的處理是可行的。

2. 這裏的資源可以是各種類型,那麼如何抽象的表示出各種類型的資源呢?

    這個問題和上面的類似,但處理方法不能一樣,因爲客戶程序查詢可訪問資源列表之後需要知道資源的類型。處理的方法是,用Class類型的ResourceClass字段表示資源的類型,用ResourceId表示這個類型下的某個ID,通過這兩個字段就可以確定資源是哪個具體的類型的實例了。

3. Authorited只是一張關聯表,只能表示有沒有訪問的權限,不能表示權限的等級,比如讀權限/寫權限,那麼如何控制權限等級呢?

     我是這麼處理的,把菜單看做是一個功能模塊,把菜單項看做是資源,而菜單細化到具體的功能,由於我們的系統裏面每個頁面的功能是相對單一的,沒有把各種身份的功能做到一起,所以每一個菜單項就可以表示權限的等級了,比如查看成績是一個菜單項,修改成績是另外一個菜單項,這樣只要控制這個人能否訪問到指定頁面就可以控制到權限等級。

 

 

以上是解決顯示合適的菜單項的方案,當訪問者進入合適的菜單項之後再查詢可訪問的資源列表,於是顯示合適的數據。由於資源是樹形結構,客戶程序還可以查詢某以某個資源實例爲父資源的某種類型的資源,這樣很容易控制數據的級聯菜單形式的現實。

 

接下來就看一下我對外提供的操作接口方法是怎麼樣的吧。

 

public interface AclController {

	/**
	 * 查詢權限,返回的資源列表中的每一項都遞歸的包含父資源直到Root
	 * @param accessor 訪問者
	 * @param moduleId 訪問的模塊ID
	 * @return 可訪問的資源列表
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public List<Resource> get(Accessor accessor, Long moduleId) throws AclDatabaseAccessException, AclAnnotationConfigurationException;

	/**
	 * 查詢權限,返回的資源列表中的每一項都不包含父資源
	 * @param accessor 訪問者
	 * @param moduleId 訪問的模塊ID
	 * @param parent 父資源
	 * @param resourceClazz 父資源Class對象
	 * @return
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public List<Resource> get(Accessor accessor, Long moduleId, Resource parent, Class resourceClazz) throws AclDatabaseAccessException, AclAnnotationConfigurationException;

	/**
	 * 修改一個權限
	 * @param oldAuthoritied
	 * @param newAuthoritied
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void modify(Authoritied oldAuthoritied, Authoritied newAuthoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;

	/**
	 * 獲取根資源
	 * @return
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public Resource getRootResource() throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	/**
	 * 增加一個資源
	 * @param resource
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void add(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	/**
	 * 刪除一個資源
	 * @param resource
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void delete(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	/**
	 * 修改一個資源
	 * @param resource
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void modify(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	/**
	 * 增加一個權限主體
	 * @param accessor
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void add(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	
	/**
	 * 刪除一個權限主體
	 * @param accessor
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void delete(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
	
	/**
	 * 修改一個權限主體
	 * @param accessor
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void modify(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;

	/**
	 * 添加一個權限
	 * @param authoritied
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void add(Authoritied authoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;

	/**
	 * 刪除一個資源
	 * @param authoritied
	 * @throws AclDatabaseAccessException
	 * @throws AclAnnotationConfigurationException
	 * @author xuke
	 */
	public void delete(Authoritied authoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;
}

 其實權限系統主要是設計,至於如何實現都是小事情,簡單說一下把,我的這個模塊裏是用spring做ioc的,數據庫操作方面考慮到效率問題所以是用的jdbc,但模仿了hibernate的Annotation的配置方式,自己實現了表和字段的映射,所以sql是自動生成的,如果數據庫改了,sql是不需要改的。

有興趣的可以看看我的整個的代碼,歡迎大牛給出寶貴意見,小弟先受了。

 

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 2308
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章