董一璠,李寶林,何先波
(西華師范大學 計算機學院,四川 南充 637000)
聯通資源管理系統是由四川南充聯通公司授權,由我處完成的一個對聯通本地資源的管理系統。管理的資源包括各類通信設備、機房或節點、桿線資源、管孔資源及客戶信息等。本軟件主要用于完成聯通南充公司的各類資源的錄入、瀏覽、查詢、統計等功能,擬采用文字表格、邏輯圖及GIS等多種方式實現對各類資源的操作和管理。開發過程中發現由于各個不同部門之間需要管理的業務模塊不盡相同,互相之間既需要連通性,有需要隔離性。所以對于聯通資源管理系統的權限授予和權限驗證提出了極大地要求。本系統采用面向對象的J2EE進行開發,系統是典型的B/S結構。所以我們采用Spring Security安全框架對整個系統的安全框架進行搭建,采用嚴格的權限控制和角色化的操作界面實現整個系統的安全性和操作界面的簡潔性。既很好的解決了系統權限控制問題,而且安全可靠,便于移植重利用。
在基于B/S結構的J2EE企業級應用系統中,客戶登陸認證、訪問授權控制是重要組成部分,Spring Security提供了一個較成熟的安全框架[1]。
Spring Security是由Acegi Security發展而來的,是Spring框架的組成部分,Spring Security框架主要提供“認證”和“授權訪問”,“認證”為用戶建立一個他所需要聲明的主題,即用戶或在你系統中執行的其他設備或系統。另一個是“授權”,授權是指已經提前建立好了某個用戶被授予的權利,能否執行某個操作,在執行之前就已經進行了授權判斷。Spring Security也支持大量的第三方驗證模型[2]。
Spring Security通過使用Servlet過濾器對Web安全性進行支持,過濾器過濾Servlet的訪問請求,將這些請求轉發給認證授權管理決策處理器進行安全處理,從而曾強了系統的訪問安全性。每一個請求發出后,至少要經過以下4個過濾器,如圖1所示。

圖1 四重安全過濾器結構Fig.1 Four security filters structure
1)集成過濾器:負責在請求剛發出的時候檢驗是否在HTTP會話中已經存儲了一個用戶的驗證信息,為其他過濾器的處理做準備。
2)認證處理過濾器:負責判斷是否為一個認證請求。如果是,相關的認證信息會從中提取出來,然后轉移給認證管理器進行處理,確定這個用戶的身份。如果不是,認證處理過濾器不做任何處理,該請求繼續前進。
3)例外轉換過濾器:負責將可能被拋出的異常“Access Denied Exception”和 “Authentication Exception”轉化為對應的HTTP響應。
4)過濾器安全攔截器:負責Web應用程序的安全攔截。檢查請求中的用戶是否是具有訪問被保護資源的的權限的用戶。它的工作依賴于認證管理器和訪問決策管理器[3]。
為了使用Spring Security框架,在WEB項目的web.xml中需作如下配置:

其中springSecurityFilterChain過濾器是Spring Security框架的總體配置,applicationContext*.xml是對所有Spring配置文件導入的配置。Spring Security的配置文件名為applicationcontext-security.xml。
在聯通資源管理系統中,因為用戶量大,所以用戶需要用數據庫中的表進行保存。表中的用戶和密碼信息的查詢信息通過UserService實現。我們的系統中UserService實現用戶認證(authentiation)和資源訪問授權(Authorization)的相關基本操作,其中包括用戶和密碼的添加、刪除、更改和查詢。在實現中,UserService需實現UserDetailsService接口,該接口也是spring認證框架要求實現的。UserDetailsService接口只包 含 一 個 方 法 :UserDetails loadUserByUsername (String username)。該方法通過用戶名去查詢用戶相關的詳細信息,返回實現UserDetails接口的類,對框架來說,其操作主要通過UserDetailsService和UserDetails實現。在我們的項目中使用類UserDetailsImpl類實現接口UserDetails, 如下是

在UserDetailsImpl中定義了一個很重要的Java Bean——uservo。在我們的項目中,User為PO對象,與數據庫中的表user的記錄對應。UserVO為VO對象,根據業務邏輯進行加工:

在UserService實現類中,通過public void init(){umapper=session.getMapper(UserMapper.class); } 實現與數據庫表及基本操作的關聯,UserMapper為CRUD操作實現接口,框架會自動實現相關類的實例化 (UserMapper.xml在mybatis配置文件中引用,UserExample與User類會在UserMapper接口框架實現中引用,框架可采用動態代理等技術得到類實例).UserVO除了包括User的信息以外,還須對User信息進一步細化,如GroupId到Group類實例,另外,授權部分,我們的系統并未在庫中實現,而是嵌在代碼中,故需找到該部分內容。這些主要在如下調用中實現(由convert2vo完 成 ):UserDetails ud= new UserDetailsImpl (convert2vo(user));由此可知,認證的基本思想及調用實現如下:
1)org.springframework.security.core.context.SecurityContext接口表示的是當前應用的安全上下文。通過此接口可以獲取和設置當前的認證對象。org.springframework.security.core.Authentication接口用來表示此認證對象。通過認證對象的方法可以判斷當前用戶是否已經通過認證,以及獲取當前認證用戶的相關信息,包括用戶名、密碼和權限等。
2)要使用此認證對象,首先需要獲取到 Security Context對象。通過 org.springframework.security.core.context.Security Context Holder類提供的靜態方法 getContext()就可以獲取。
3)通過 SecurityContext對象的 getAuthentication()方法可以得到認證對象。通過認證對象的 getPrincipal()方法就可以獲得當前的認證主體,通常是UserDetails接口的實現。
4)典型的認證過程就是當用戶輸入了用戶名和密碼之后,UserDetailsService通過用戶名找到對應的UserDetails對象,接著比較密碼是否匹配。如果不匹配,則返回出錯信息;如果匹配的話,說明用戶認證成功,就創建一個實現了Authentication接口的對象,如 org.springframework.security.authentication.Username Password AuthenticationToken類的對象。再通過SecurityContext的setAuthentication()方法來設置此認證對象。
綜上所述,整個登錄過程如圖2所示。

圖2 登陸安全驗證結構Fig.2 Login Security verification structure
系統要首先根據需要定義好角色,并為每一角色分配合適的訪問權限,然后再根據用戶的職責和權利指派不同的角色。這樣就實現了權限和用戶的邏輯分離,使得權限分配的靈活性問題得以解決。在聯通資源管理系統中,我們也是按照聯通公司對企業人員的分組對角色進行分配的,對于每個模塊都要有相應的讀(R)寫(W)查(S)權限的管理。不同分組用戶對不同模塊具有不同的權限,需要分別授予,如圖3所示。

圖3 權限控制結構Fig.3 Authority manage structure
系統的角色通過枚舉RoleEnum實現,這也是用戶管理權限設置部分的信息來源:

授權是以組的方式存在,故一個Authority有組標識,其權限由其分配的角色而定,一個組可能對應多個Authority。

系統用戶的權限獲取在UserService.getAuthorities方法中實現,根據枚舉內容賦予所有權限(讀、寫和執行),代碼如下:

一般用戶的權限則通過組 AuthorityService.getAuthoritiesByGroupId方法實現,在authority表中內容如圖4所示。

圖4 用戶組權限表Fig.4 User group permissions list
在spring安全機制中,有大量的如下配置:

特別是在applicationContext-security.xml中。這是在配置文件中集中配置允許登入的權限。該方式主要針對URL地址及參數過濾,主要用于控制網頁整體的訪問,可在實現中對各網頁名字和存儲路徑進行合理規劃達到安全控制的目的。另外,也可通過struts配置實現對方法訪問的控制,但struts配置較龐大。還有一種方式,是通過jsp的安全按標簽實現對網頁元素的顯示控制,例如

authorize標簽用來決定它的內容是否會被執行,另外,<sec:authentication?標簽用于訪問當前的Authentication對象,保存在安全上下文中。
通過UserDetails接口中的getAuthorities()方法實現的,該方法返回一權限名字字符串集合。本系統的具體實現如下:

上面代碼中,GrantedAuthorityImpl包含了字符串名(role字符串成員變量),并實現了GrantedAuthority接口。綜上可知,UserService實現了框架所需的所有操作,UserVO包含了安全相關的所有信息,UserDetailsImpl實現了框架所需要的接口。
在基于J2EE的企業級B/S項目中,安全是一個自發展開始以來一直非常受到重視的內容。在系統的開發過程中,對于代碼的復用率,可移植性等問題,一直是程序開發人員的頭等大事。而Spring Security為我們提供了一個十分便利有效的管理模塊。通過對端口的加載,和對攔截器與權限的配置,可以讓你的系統在很短的時間內,就擁有一個良好的安全機制。在使用過程中發現的問題如下:
1)由于采用將用戶信息保存在session中,當修改或更新了用戶信息后,無法立刻將新的用戶信息用于當前用戶。實時更新用戶信息,是目前Spring Security的一個大問題[4]。
2)應該考慮如何引入spring AOP對方法進行控制。
[1]蒲子明,許勇,王黎.Struct+Hibernate+Spring整合開發技術詳解[M].北京:清華大學出版社,2010.
[2]佚名.Spring安全框架 [EB/OL].[2012-11-18]http://www.oschina.net/p/spring+security.
[3]佚名.Spring Security介紹 (4)[EB/OL].[2012-11-18]http://www.4ucode.com/study/topic/353380.
[4]馬楠.基于Spring的J2EE安全框架的研究與應用[D].北京:北京郵電大學,2009.
[5]丁振凡.基于Spring Security的Web資源訪問控制[J].宜春學院學報,2012(8):36-1250.DING Zhen-fan.Access control for web resources based on spring security[J].Journal of Yichun University,2012(8):36-1250.
[6]熊昊.基于Spring的Acegi安全框架及其應用研究[D].長沙:國防科學技術大學,2008.