Spring Security 3.0.0.M1 釋出

工程 | Luke Taylor | 2009 年 6 月 3 日 | ...

我們很高興地宣佈 Spring Security 3.0 的第一個里程碑版本現已可供 下載。該版本也可透過 Maven 里程碑儲存庫獲得,地址為http://maven.springframework.org/milestone。與 Spring 3.0 一樣,這是第一個要求最低 JDK 1.5 才能執行的釋出版本,並且還需要 Spring 3.0,因此如果您還沒有使用 Spring 3.0,應該獲取 Spring 3.0.0.M3 版本。那麼,在這個版本中有哪些新功能和變化呢?

基於表示式的訪問控制

此版本首次包含我們 Spring-EL 的授權支援預覽。您現在可以在方法註解和 Web 安全中使用表示式。與熟悉的屬性和投票者機制相比,這開闢了許多新的可能性。一個簡單的例子可能是一個好的開始。這裡有一個針對 Web 應用程式的例子,使用了安全名稱空間

  <http use-expressions="true">
     <intercept-url pattern="/secure/**" access="hasRole('ROLE_SUPERVISOR') and hasIpAddress('192.168.1.0/24')" />
     ...
  </http>;

內建的hasRole('ROLE_SUPERVISOR')表示式很簡單——它只是檢查當前使用者的許可權列表,如果使用者擁有給定角色,則返回 true。但我們添加了一個額外的表示式來指定發起請求的 IP 地址必須在子網/掩碼引數定義的範圍內。這可能對您的網路設定有用,也可能無用,但這說明了基於表示式的方法有多麼強大。以前包含在“access”XML 屬性中的安全屬性列表已被布林表示式替換。如果求值為“true”,則授予訪問許可權。如果求值為“false”,則拒絕訪問。

@Pre 和 @Post 註解

方法安全比我們剛才看到的用於 Web 請求的簡單允許或拒絕要複雜一些。為了對方法安全使用表示式提供更全面的支援,我們引入了四個新註解,它們可以包含應用於方法呼叫之前和之後的表示式屬性。要啟用對它們的支援,在global-method-security名稱空間元素上有一個新屬性

    <global-method-security pre-post-annotations="enabled"/>

最明顯有用的註解是@PreAuthorize它控制著方法是否可以實際呼叫。例如(來自“Contacts”示例應用程式)


    @PreAuthorize("hasRole('ROLE_USER')")
    public void create(Contact contact);

這意味著只有擁有“ROLE_USER”角色的使用者才能獲得訪問許可權。這沒什麼新東西。但關於

  
    @PreAuthorize("hasPermission(#contact, 'admin')")
    public void deletePermission(Contact contact, Sid recipient, Permission permission);

在這裡,我們實際上使用方法引數作為表示式的一部分來決定當前使用者是否對給定的聯絡人擁有“admin”許可權。“hasPermission()表示式透過應用程式上下文連結到 Spring Security ACL 模組(有關如何實現這一點,請參閱 Contacts 示例配置)。您可以按名稱訪問任何方法引數作為表示式變數,前提是您的程式碼已編譯除錯資訊。任何 Spring-EL 功能都可以在表示式中使用,因此您也可以訪問引數上的屬性。例如,如果您希望某個方法只允許使用者訪問,該使用者的使用者名稱與聯絡人匹配,您可以編寫


    @PreAuthorize("#contact.name == principal.name)")
    public void doSomething(Contact contact);

這裡我們正在訪問另一個內建表示式,即當前 Spring Security 的“principal”Authentication物件,該物件從安全上下文中獲取。您還可以使用表示式名“authentication”直接訪問Authentication物件本身。授權也可以在方法呼叫發生後進行,使用@PostAuthorize註解。要訪問方法的返回值,請在表示式中使用內建名稱“returnObject”。

過濾

您可能已經知道,Spring Security 還支援集合和陣列的過濾,現在可以使用表示式來實現。這通常在方法的返回值上執行。例如
    
    @PreAuthorize("hasRole('ROLE_USER')")
    @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
    public List getAll();

當與@PostFilter註解一起使用時,Spring Security 會遍歷返回的集合,並刪除其中 supplied 表示式為 false 的元素。“filterObject”名稱指的是集合中的當前物件。您也可以在方法呼叫之前進行過濾,使用@PreFilter,儘管這可能是一個不太常見的要求。語法相同,但如果有一個以上的引數是集合型別,則必須使用該註解的“filterTarget”屬性按名稱選擇一個。

程式碼庫重構

在 3.0 版本之前,Spring Security 的大部分程式碼都包含在spring-security-corejar 中。隨著時間的推移,隨著更多功能的新增,跟蹤程式碼庫內部和第三方庫的依賴關係變得越來越困難。例如,使用者很難確定核心 Maven pom.xml 中列出的依賴項中有哪些是框架中特定功能集所必需的。此外,原始的包結構和類名自 2003 年框架起源於 Acegi Security 以來就一直存在,當時只支援少數基本身份驗證機制。隨著程式碼量的增加和功能集的擴充套件,這種包結構已經開始顯得陳舊。
Spring Security 2.0.4 Package Structure

Spring Security 2.0.4 包結構

上圖顯示了 2.0.4 版本中 core、core-tiger、cas-client 和 acl jar 的高階包圖,由 Structure101 生成。您不必是程式碼結構專家就能意識到這裡存在一些問題。有很多迴圈引用,包之間沒有清晰的整體依賴結構。包跨 jar 邊界分割也存在一些問題,這可能導致 OSGi 問題。程式碼結構中的這種脆弱性可能會在 Spring Security 發展過程中導致維護開銷,因此決定在 3.0 版本中重構程式碼,為未來的開發提供一個穩定的基礎。讓我們看看現在的組織結構。

專案 jar

我們首先將 core 分成幾個 jar。現在spring-security-corejar 只包含基本的身份驗證和訪問控制程式碼,並且更加清晰。例如,它沒有 LDAP 或 servlet API 的依賴項,現在有單獨的 jar 用於 Web 相關程式碼和 LDAP。我們還將名稱空間解析程式碼分離到一個單獨的 jar 中,因為它依賴於大多數其他 jar,並且不公開您可能直接在應用程式中使用的任何公共 API。只有在使用 Spring Security 名稱空間配置的應用程式上下文 XML 檔案時,才需要使用它。主要的專案 jar 如下表所示。
Jar 名稱 描述 何時使用 根包(s)
spring-security-core 核心身份驗證和訪問控制類和介面。遠端支援和基本預配 API。 任何使用 Spring Security 的應用程式都必需。支援獨立應用程式、遠端客戶端、方法(服務層)安全和 JDBC 使用者預配。 org.springframework.security.coreorg.springframework.security.accessorg.springframework.security.authenticationorg.springframework.security.provisioningorg.springframework.security.remoting
spring-security-web 過濾器和其他 Web 安全基礎設施及相關程式碼。任何具有 servlet API 依賴項的內容。 如果您需要 Spring Security Web 身份驗證服務和基於 URL 的訪問控制 org.springframework.security.web
spring-security-config 名稱空間解析程式碼。 如果您正在使用 Spring Security XML 名稱空間。 org.springframework.security.config
spring-security-ldap LDAP 身份驗證和預配程式碼。 如果您需要使用 LDAP 身份驗證或管理 LDAP 使用者條目。 org.springframework.security.ldap
spring-security-acl 領域物件 ACL 實現。 如果您需要對應用程式中的特定領域物件例項應用安全性。 org.springframework.security.acls
spring-security-cas-client Spring Security 的 CAS 客戶端整合。 如果您想將 Spring Security Web 身份驗證與 CAS 單點登入伺服器一起使用。 org.springframework.security.cas
spring-security-openid OpenID Web 身份驗證支援。 如果您需要對外部 OpenID 伺服器進行使用者身份驗證。 org.springframework.security.openid
現在 jar 級別上的關注點分離得更清楚了。例如,只有在編寫 Web 應用程式時才需要 Web jar(及其傳遞依賴項)。這使得程式碼更容易導航和理解。現在構成了我們上面為 2.0.4 版本檢視的相同程式碼集的 Spring Security 3.0 jar 之間的依賴關係如下所示
Spring Security 3.0 jars

Spring Security 3.0.0.M1 Jar 依賴關係

包結構

這些 jar 的包佈局如下所示。可以看到,不再有任何迴圈引用,結構也更清晰了。
Spring Security 3.0.0.M1 Package Structure

Spring Security 3.0.0.M1 包結構

其中 core 包及其子包包含框架中使用的基本類和介面,core jar 中的另外兩個主要包是 authenticationaccessaccess 包包含訪問控制/授權程式碼,如 AccessDecisionManager 和相關的基於投票者的實現,攔截和方法安全基礎設施,註解類以及對 Spring Security 3.0 基於表示式的訪問控制的支援。authentication 包包含 AuthenticationManager 和相關類(如身份驗證異常類),基於 DAO 的簡單身份驗證提供程式和密碼編碼器。

其他雜項更改

重新命名類

程式碼庫中的一些類名也開始顯得陳舊。例如,AbstractProcessingFilter現在是AbstractAuthenticationProcessingFilter,以及它最常見的具體子類AuthenticationProcessingFilter現在是UsernamePasswordAuthenticationProcessingFilter,因為框架中現在有很多過濾器處理身份驗證請求。其對應的AuthenticationEntryPoint現在是LoginUrlAuthenticationEntryPoint。名稱不明確的ObjectDefinitionSource已重新命名為SecurityMetadataSource,以及相應的屬性AbstractSecurityInterceptor也已類似地重新命名。實現類和子介面也已類似地重新命名。HttpSessionContextIntegrationFilter現在是SecurityContextPersistenceFilter,並有一個可插拔策略來控制它如何儲存安全上下文——它不必儲存在HttpSession.

中。身份驗證成功或失敗時的重定向/轉發

另一個問題是AbstractProcessingFilter,控制瀏覽器在身份驗證成功或失敗後重定向到的目標的方式有很多種。存在屬性和策略的混合使用。在 Spring Security 3.0.0.M1 中,這些已被兩個獨立的策略取代AuthenticationSuccessHandler還是AuthenticationFailureHandler,它們完全負責處理目標。請檢視這些介面的 Javadoc,並檢視問題 SEC-745 以獲取更多資訊。

參考手冊和網站更新

顯然,3.0 參考手冊仍在開發中 :-),但我們已經做了一些更新。名稱空間技術概述章節應該能提供框架的合理概覽。請隨時透過問題跟蹤器提交任何想法或補丁。同樣,如果您發現任何錯誤,當然也要報告。

專案網站也已更新。FAQ 有一些新問題,還有一個新頁面連結到演示影片和線上文章。請檢視並告知我們您希望在那裡看到什麼(外部安全連結頁面已在開發中)。

結論

Spring Security 3 還有很多工作要做,但我們希望您能嘗試此里程碑版本,並對新的表示式語言支援提供反饋。您可以在Jira Changelog 中找到迄今為止所有更改的完整列表,您也可以在那裡找到指向當前專案路線圖的連結。

社群論壇是提問關於 Spring Security 用法或討論新功能最佳地點。或者,如果您發現任何問題,可以提交一個Jira Issue

我們希望您喜歡使用Spring Security

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱