安全管理是最復(fù)雜也是最難以理解的功能模塊,理論上僅對系統(tǒng)管理員開放該功能。總的來看安全管理主要分為用戶管理、用戶權(quán)限、角色來分派權(quán)限。
在介紹安全管理之前,先讓我們對一些關(guān)鍵字有所了解。
關(guān)鍵詞:
ü
用戶:權(quán)限的持有者。一般來說通過登錄賬號對應(yīng)客觀世界的一個人,一個用戶有且只能在一個部門下。用戶在權(quán)限系統(tǒng)中又分為不同的類型:一般用戶/超級管理員(不受權(quán)限限制,在應(yīng)用系統(tǒng)中有無限的權(quán)力)
ü
權(quán)限:一個權(quán)限對應(yīng)一個功能,這個功能可以是頁面/頁面中的表單元素(如按鈕/文本框)/業(yè)務(wù)層的方法,在技術(shù)層面看,一個權(quán)限只是一個字符串。目的是用戶擁有的權(quán)限與功能的配置權(quán)限做匹配,以達到權(quán)限驗證效果
ü
角色:權(quán)限的集合,因為權(quán)限的顆粒度太小無法滿足對一個完整業(yè)務(wù)授權(quán)管理的描述。如會計角色,要求可以增加、刪除與修改會計科目(或更多),而增加或刪除會計科目均是一個功能單元應(yīng)分別對應(yīng)各自的權(quán)限。在應(yīng)用系統(tǒng)中,一個角色實際上就是一個工作職能所擁有的權(quán)限集合。
ü
組織結(jié)構(gòu):是用戶與部門的總稱。部門應(yīng)是樹形結(jié)構(gòu)。之所以在權(quán)限管理中引用組織結(jié)構(gòu),是因為影響權(quán)限對數(shù)據(jù)的篩選范圍。對于范圍可以分為:用戶級(當(dāng)前用戶自己創(chuàng)建的記錄)/系統(tǒng)級(所有記錄)/當(dāng)前部門級(當(dāng)前用戶所在的部門中所有用戶創(chuàng)建的記錄)/部門級/部門及子部門級。對于后兩種類型還需要授權(quán)時給出參考部門。
操作方案:
方案1. 將多個權(quán)限直截分派給用戶
方案2. 將多個權(quán)限合并為一個角色,再將多個角色分派給用戶
此兩種方案是按系統(tǒng)復(fù)雜程度逐級遞增的,從權(quán)限的維護難度來看也是逐級遞增。在此要注意,在一個應(yīng)用系統(tǒng)中您只能選擇兩種方案其中的一種來維護您的權(quán)限管理,強烈不推薦多種方案在同一個應(yīng)用系統(tǒng)中同時管理的情況出現(xiàn)。這樣會導(dǎo)致后期系統(tǒng)維護的混亂,嚴重時有可能產(chǎn)生系統(tǒng)癱瘓!
通過用操作:
在分派某些查詢權(quán)限時頁面中會顯示范圍與部門

在范圍中只有部門級與部門及子部門極,部門一列才會顯示。權(quán)限控制范圍(以訂單為例)如下:
²
用戶級:只能看到當(dāng)前用戶自己所創(chuàng)建的訂單
²
當(dāng)前部門級:如果當(dāng)前用戶與訂單的創(chuàng)建人在同一個部門,則當(dāng)前用戶在查詢訂單時可以看到該訂單
²
部門級:可以為當(dāng)前用戶指定一個部門,使他只能看到這個部門下所有員工所創(chuàng)建的訂單
²
部門及子部門級:可以為當(dāng)前用戶指定一個部門,使他可以能看到這個部門包括這個部門下所有的子孫部門中所有員工所創(chuàng)建的訂單(部門或者說是組織結(jié)構(gòu)應(yīng)是樹形結(jié)構(gòu))
²
系統(tǒng)級:能看到所有訂單不受到任何組織結(jié)構(gòu)及創(chuàng)建人的限制
用戶管理:
提供系統(tǒng)管理員對企業(yè)內(nèi)與企業(yè)外用戶的安全認證管理。雖然在此處提供刪除用戶的功能,但不推薦使用。一般來說無論是新增還是刪除員工、客戶聯(lián)系人都應(yīng)是人力資源或是銷售部門來管理,而系統(tǒng)管理員只對于這些用戶做授權(quán)或分派帳號與密碼。

²
姓名:用戶的真實姓名,見意系統(tǒng)管理員不要修改該內(nèi)容,應(yīng)由相關(guān)部門來維護該用戶的姓名,如人力資源部、銷售部、采購部的人員來修改該用戶的姓名
²
部門:是個抽象的概念,如果當(dāng)前用戶是企業(yè)內(nèi)部員工則它是企業(yè)內(nèi)的部門或是分公司;如果當(dāng)前用戶是客戶聯(lián)系人則它是客戶;如果當(dāng)前用戶是供應(yīng)商聯(lián)系人則它是供應(yīng)商。同樣的該信息應(yīng)用相關(guān)部門的負責(zé)來維護,系統(tǒng)管理員不應(yīng)隨意修改
²
帳號:當(dāng)前用戶登錄系統(tǒng)的帳號
²
密碼:當(dāng)前用戶登錄系統(tǒng)的密碼,注意密碼經(jīng)過了加密處理在修改密碼時一定要將該文本框中的內(nèi)容全部清空后重新輸入,否則用戶將無法登錄系統(tǒng)
²
帳號可用:用以設(shè)定該帳號是否可用,如果為否則該帳號無效,用戶不能登錄系統(tǒng)
²
加鎖:對該帳號加鎖,加鎖后的帳號無法登錄到系統(tǒng)。加鎖與不可用表現(xiàn)形式相同即用戶無法登錄系統(tǒng);區(qū)別在于加鎖相當(dāng)于將凍結(jié)該帳號在一段時間后來可以解鎖,而不可用則是這個帳號常期失效后期對該帳號的用戶不予維護例如員工離職時一定要將帳號設(shè)為不可用而非加鎖
²
有效期至:可以為某個用戶的帳號設(shè)置有效期,當(dāng)超過有效期即使帳號是可用未加鎖也無法登錄到系統(tǒng)中,如果不填寫用效期則視為該帳號不受時間限制始終可用
²
用戶類型:分為
n
超級管理員:不受任何權(quán)限的限制,在應(yīng)用系統(tǒng)中有無限的權(quán)力,可以看到與修改全部內(nèi)容
n
一般用戶:只能看到與修改他/她所擁有權(quán)限的內(nèi)容
n
管理員:可以將自己已有的權(quán)限分派給他人
用戶權(quán)限:
對應(yīng)操作方案中的方案1,即將權(quán)限直截分派給指定的用戶。這種方案適用于小型且用戶數(shù)量很少的應(yīng)用系統(tǒng)。該方案優(yōu)點是操作直觀易于理解,缺點是不易管理。
在為用戶分派權(quán)限時,可以通過三種操作方式來完成。

在操作過程中,當(dāng)您選擇在不同用戶間來回切換時,當(dāng)前頁面會自動刷新在“事項”一列只有是該用戶所擁有的權(quán)限才會被選中,您可以在此為用戶添加權(quán)限。頁面最上部的是一排菜單項,在每個菜單項中都會有多個權(quán)限,在您在不同的菜單項中切換時,頁面底部的權(quán)限列表會隨之改變。對于權(quán)限范圍與部門的處理請參見通用操作
3.
通過
按鈕,可以同時為多個用戶分配多個權(quán)限。

在操作過程中,你可以通過查詢條件查詢到您要選擇的用戶,人員列表的最左則提供選取人員的復(fù)框,即表示您要對這些選中的用戶進行批量授權(quán)。初始時權(quán)限列表的“事項”一列均未選中,您可以在此為選中的多個用戶添加權(quán)限。頁面中部的是一排菜單項,在每個菜單項中都會有多個權(quán)限,在您在不同的菜單項中切換時,頁面底部的權(quán)限列表會隨之改變。對于權(quán)限范圍與部門的處理請參見通用操作
“單用戶批量授權(quán)”與“多用戶批量授權(quán)”的差異在于,在單用戶批量授權(quán)中您可以看到所選中的用戶目前所擁有的權(quán)限,而多用戶批量授權(quán)則不能。
注意,無論是單用戶批量授權(quán)還是多用戶批量授權(quán)均不提供權(quán)限的刪除功能,原因是同一個權(quán)限在同一個用戶中有可能會有多個權(quán)限范圍不同的副本,系統(tǒng)無法判斷要刪除這個用戶這個權(quán)限的那一個副本。如果要為某個用戶刪除某些權(quán)限,可以通過用戶權(quán)限列表刪除之。
角色:
對應(yīng)操作方案中的方案2,即將多個權(quán)限合并為一個角色,再將該角色分派給指定的用戶。這種方案適用于中小型企業(yè)的應(yīng)用系統(tǒng)。該方案優(yōu)點操作簡捷使用得當(dāng)配置效率會很高,強烈推薦使用該方案實現(xiàn)安全管理。

²
角色名稱:必須填寫項,為角色定義一個名稱中英文均可
²
描述:對該角色的描述
²
顯示信息:沒有意義,可以不填
在操作過程中,您必須為角色賦予一個名稱,并填寫該角色的描述信息,以方便日后記憶。頁面底部的權(quán)限列表右側(cè)的“事項”一列會顯示該角色所擁有的權(quán)限,您可以在此為角色添加權(quán)限也可以為角色刪除某些權(quán)限。頁面中部的是一排菜單項,在每個菜單項中都會有多個權(quán)限,在您在不同的菜單項中切換時頁面底部的權(quán)限列表會隨之改變。對于權(quán)限范圍與部門的處理請參見通用操作
步驟2. 將角色分派給用戶

在操作過程中,你可以通過查詢條件查詢到您要選擇的用戶,人員列表的最左則提供選取人員的復(fù)框,即表示您要對這些選中的用戶分派當(dāng)前角色。頁面的左下方是當(dāng)前角色所擁有的權(quán)限,頁面的右下方為所有擁有當(dāng)前角色的用戶列表,您可以通過用戶列表“事項”
刪除指定用戶所擁有的當(dāng)前角色。
目的
一般對于應(yīng)用系統(tǒng)的授權(quán)過程:
權(quán)限
à角色(部門) à用戶
過程描述:管理員將所要分組的權(quán)限分派給一個角色(一般會對應(yīng)實際工作中一個崗位如出納/倉庫管理員…),并為當(dāng)前角色指定一個部門(表示這個崗位是對哪個部門的管理)。
由此我們會發(fā)現(xiàn),這個授權(quán)過程是鏈式的,即授權(quán)是一環(huán)套一環(huán)的,沒有上一個環(huán)節(jié)的支持下一個環(huán)節(jié)就不能工作。本系統(tǒng)的實現(xiàn)目的正是為了打破授權(quán)的這種鏈式結(jié)構(gòu),實現(xiàn)在不同授權(quán)環(huán)節(jié)間的跳躍。如可以直接為用戶分派權(quán)限,為用戶分配角色等。
相關(guān)技術(shù)與依賴
Acegisecurity是基于SpringFramework的Web應(yīng)用中安全框架,通過過濾器(javax.servlet.Filter)與攔截器(org.aopalliance.intercept.MethodInterceptor),于web的所請求的頁面與所調(diào)用的方法進行攔截。以達到權(quán)限驗證的目的。在本系統(tǒng)中作為身份驗證與技術(shù)層上的授權(quán)實現(xiàn)的基本骨架。本文檔假設(shè)對Acegi框架已有全面的了解。
Spring是AOP與IOC功能強大的邏輯層框架,本系統(tǒng)中邏輯層的調(diào)用均基于該框架
限制
ü
本系統(tǒng)所有驗證與授權(quán)均是基于數(shù)據(jù)庫的,不支持其它方式業(yè)務(wù)層面上的授權(quán)
ü
由于采用上述相關(guān)技術(shù)本系統(tǒng)僅限于在web上的應(yīng)用,不支持C/S結(jié)構(gòu)
ü
由于復(fù)雜度與適用性的原因,本系統(tǒng)不支持頁面中各表單元素的權(quán)限可配置
ü
為了達到與部門有關(guān)的數(shù)據(jù)過濾的效果,所有業(yè)務(wù)相關(guān)的表中都要多加一個creator字段,作用是識標當(dāng)前記錄的創(chuàng)建人(由創(chuàng)建人可以找到部門),并且與業(yè)務(wù)表對應(yīng)的POJO的屬性名也應(yīng)為creator
客戶端用戶授權(quán)處理
ü
權(quán)限管理(Authority):所有業(yè)務(wù)組件的權(quán)限均應(yīng)由平臺生成器自動生,并自動插入到數(shù)據(jù)庫表,不提供終端用戶對權(quán)限操作界面。如果開發(fā)階段只能手動將權(quán)限插入數(shù)據(jù)庫表中。
ü
角色管理(Role/ RoleAuthority):在功能上分為角色的創(chuàng)建與刪除這兩部分
1)
創(chuàng)建角色:創(chuàng)建角色的過程實際上也是為該角色分派權(quán)限的過程。按菜單層次結(jié)構(gòu)列出所有權(quán)限(如果是管理員則只能列出所擁有的權(quán)限),并且只是權(quán)限類型是查詢的,才會顯示參考部門與范圍,默認部門為空,范圍為系統(tǒng)級。保存時,在Role表中增加一條記錄,在RoleAuthority表根據(jù)終端用戶所選擇的權(quán)限及參考部門/范圍等信息,增加n記錄
2)
刪除角色:首先是否有用戶引用< UserRole >該角色,如果有引用則客戶端拋出警告,否則刪除Role/ RoleAuthority的相關(guān)記錄
ü
分派權(quán)限管理(UserAuthority):左側(cè)是組織結(jié)構(gòu)樹右側(cè)為以菜單層次結(jié)構(gòu)的權(quán)限列表(如果是管理員則只能列出所擁有的權(quán)限) ,并且只是權(quán)限類型是查詢的,才會顯示參考部門與范圍,默認部門為空,范圍為系統(tǒng)級。
ü
分派角色(UserRole):左側(cè)是組織結(jié)構(gòu)樹右側(cè)為角色列表,將與該角色s對應(yīng)的<RoleAuthority>的信息賦到<UserAuthority>表中
頁面表單的權(quán)限控制:由Acegi提供的taglib控制
對象定義源資源格式
平臺為了方便對權(quán)限的對象定義源資源進行管理與擴展提供兩種解決方案
方案一 現(xiàn)資源束形式管理
為了系統(tǒng)可以批量加載對象定義源實現(xiàn)資源束形式的管理,應(yīng)提供對象定義源資源束格式的規(guī)范
1. 所有對象定義源的資源束文件均為properties文件,文件格式按properties規(guī)范處理,文件名為*-security.properties.生成器會自動將這些文件生成在java源代碼的相應(yīng)的服務(wù)包下
2. 文件內(nèi)容針對不同的安全功能提供不同的開始/截止符作用功能分隔。它們分別為對于URL安全控制的為WEB_SECURITY/WEB_SECURITY_END,對于業(yè)務(wù)方法安全控制的開始/截止符分別為BUSINESS_SECURITY/BUSINESS_SECURITY_END。
方案二 數(shù)據(jù)庫表形式管理
將所有權(quán)限對象定義源存放到數(shù)據(jù)庫表HI_PrivilegeResource中,表結(jié)構(gòu)如下:
字段名
|
數(shù)據(jù)類型
|
唯一
|
描述
|
id
|
int
|
Y
|
主鍵ID
|
version
|
Int
|
|
樂觀鎖定時的版本控制
|
authorityName
|
String(200)
|
Y
|
權(quán)限名
|
viewLayer
|
String(200)
|
|
表現(xiàn)層的動作,一般的對應(yīng)一個action的url
|
veiwExtAuthNames
|
String(200)
|
|
該表現(xiàn)層動作還可容許訪問的權(quán)限名,如果是多個權(quán)限用逗號(,)分隔
|
businessLayer
|
String(500)
|
|
業(yè)務(wù)層的方法,一般是類的全限定名包括方法名
|
bizExtAuthNames
|
String(200)
|
|
該業(yè)務(wù)層方法還可容許訪問的權(quán)限名,如果是多個權(quán)限用逗號(,)分隔
|
與權(quán)限相關(guān)的配置文件
平臺對于權(quán)限相關(guān)的配置文件存放在WEB_HOME/WEB-INFOr/config目錄下,文件名為appContext-security.xml是一個Spring的配置文件,由于該文件較為復(fù)雜在此僅介紹常用的幾處,具體的每段配置的目的請參見附錄中Acgei與配置文件相關(guān)的類說明
<bean id="securityManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.hi.framework.security.service.impl.SecurityManagerImpl">
<property name="DAO" ref="org.hi.framework.dao.DAO"/>
<property name="userClass" value="org.hi.base.organization.model.HiUser"/>
<property name="userAuthorityClass" value="org.hi.framework.security.model.UserAuthority"/>
</bean>
</property>
</bean>
安全管理器是后臺的服務(wù)類,用于獲取給定用戶(即當(dāng)前登錄用戶)的相關(guān)信息包括該用戶的POJO、該用戶所擁有的權(quán)限、角色等。UserContextHelper這個類在我們開發(fā)過程中經(jīng)常用到它可以獲得當(dāng)前用戶的所有信息,而這些信息的來源與組裝過程就是在安全管理器這個服務(wù)類中完成的。該類中的userClass屬性是指定用戶POJO的類型,如果我們通過擴展實體的方式擴展了HiUser,應(yīng)將該類型更改為擴展后實體的POJO類型
<bean id="filterInvocationInterceptor" class="org.hi.framework.security.acegi.ResourceBindleFilterSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="mappingLocations"><value>classpath*:/**/*-security.properties</value></property>
<property name="alwaysReauthenticate" value="true"/>
<property name="runAsManager"><ref bean="runAsManager"/></property>
</bean>
表現(xiàn)層也就是Action的攔截器,通過HttpFilter在servlet執(zhí)行任意一個action之前先被攔截認證當(dāng)前用戶是否有執(zhí)行該url的權(quán)限,上面是資源束形式的管理方式,如要實現(xiàn)數(shù)據(jù)庫表形式的管理方式,如下
<bean id="filterInvocationInterceptor" class="org.hi.framework.security.acegi.DataBaseFilterSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="load" value="true"></property>
<property name="alwaysReauthenticate" value="true"/>
<property name="runAsManager"><ref bean="runAsManager"/></property>
</bean>
對于業(yè)務(wù)層的方法攔截器,資源束形式管理/數(shù)據(jù)庫表形式管理,在配置上完全一致。
1.1
組織結(jié)構(gòu)
從企業(yè)管理的角度來看,組織結(jié)構(gòu)是指對于工作任務(wù)如何進行分工、分組和協(xié)調(diào)合作。從而使企業(yè)在組織上更加結(jié)構(gòu)化、合理化以提高生產(chǎn)效率;從程序設(shè)計的角度來看,軟件系統(tǒng)應(yīng)適應(yīng)企業(yè)組織在結(jié)構(gòu)上的不斷變化。
為了達到如上的要求,平臺在設(shè)計上對于Hi_Org和Hi_User是兩個抽象的表結(jié)構(gòu),對于Hi_Org來說它可以是公司、部門、客戶、供應(yīng)商等等;而對于Hi_User來說它可以是員工、客戶聯(lián)系人、供應(yīng)商聯(lián)系人等。因此在開發(fā)時可以通過平臺繼承實體的方式,擴展組織與人員實體從而實現(xiàn)不同類型的組織結(jié)構(gòu)。
數(shù)據(jù)庫表結(jié)構(gòu)
Hi_Org組織表
字段名
|
數(shù)據(jù)類型
|
唯一
|
描述
|
ID
|
int
|
Y
|
主鍵ID
|
version
|
int
|
|
樂觀鎖定時的版本控制
|
orgName
|
String(50)
|
|
部門
|
orgNum
|
String(10)
|
|
部門編號
|
manager
|
int
|
|
部門的管理者,<User>
|
parentOrg
|
int
|
|
父部門,默認為0 <Org>
|
address
|
String(100)
|
|
地址
|
description
|
String(500)
|
|
備注/描述
|
Hi_User用戶表
字段名
|
數(shù)據(jù)類型
|
唯一
|
描述
|
ID
|
int
|
Y
|
主鍵ID
|
version
|
Int
|
|
樂觀鎖定時的版本控制
|
userName
|
String(30)
|
Y
|
用戶的登錄賬號
|
password
|
String(100)
|
|
用戶密碼,在數(shù)據(jù)庫要求加密
|
country
|
int
|
|
對應(yīng)枚舉表[Language],是i18n的語種
|
timeZone
|
int
|
|
對應(yīng)枚舉表[TimeZone],是i18n的時區(qū)
|
accountEnabled
|
int
|
|
[YesNo],該帳號是否可用
|
accountLocked
|
int
|
|
[YesNo],是否鎖住該帳號
|
expiredDate
|
Date
|
|
帳號的失效日期,null為永不失效
|
credentialsExpired
|
int
|
|
[YesNo],密碼是否過期,預(yù)留不實現(xiàn)
|
fullName
|
String(30)
|
|
姓名
|
org
|
int
|
|
用戶所在的部門
<Org>
|
gender
|
int
|
|
性別
|
address
|
String(200)
|
|
地址
|
phone
|
String(50)
|
|
電話
|
mobile
|
String(50)
|
|
手機
|
zip
|
String(30)
|
|
郵編
|
SSN
|
String(50)
|
|
證件號
|
mail
|
String(100)
|
|
電子郵箱
|
userMgrType
|
int
|
|
[ScurityUserMgrType] 超級管理員/管理員/一般用戶
|
description
|
String(500)
|
|
備注/描述
|