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.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模組中(請參考聯絡人範例來了解是如何實現的)。你可以使用名稱,作為表達式變數來存取任何方法參數,前提是你的程式碼在編譯的時候有偵錯資訊。任何Spring-EL的功能都可以在表達式中使用,所以你也可以存取引數中的屬性。舉例來說,如果你希望特定的方法只允許其使用者名稱與聯絡人使用者名稱相符的使用者存取,你可以這樣寫


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

在這裡,我們正在存取另一個內建表達式,它是從安全性上下文中取得的當前 Spring SecurityAuthentication物件的 "principal"。您也可以使用表達式名稱 "authentication" 直接存取Authentication物件本身。也可以在使用@PostAuthorize註解後,在方法調用完成後執行授權。要存取方法的回傳值,請在表達式中使用內建名稱 "returnObject"。

篩選

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

當與@PostFilter註解一起使用時,Spring Security 會迭代回傳的集合,並移除提供的表達式為 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-tiger、cas-client 和 acl jar 的高階套件圖,由 Structure101 產生。您不必成為代碼結構的專家就能意識到這裡存在一些問題。存在許多循環參考,並且套件中沒有清晰的整體依賴性結構。套件跨 jar 邊界分割也存在一些問題,這可能會導致 OSGi 出現問題。代碼結構中的這種脆弱性可能會在 Spring Security 發展過程中造成維護開銷,因此決定重組 3.0 版本的代碼,以便為未來的開發提供穩定的基礎。讓我們看看現在的組織方式。

專案 Jar

我們做的第一件事是將核心拆分為多個 jar。spring-security-corejar 現在僅包含基本驗證和存取控制代碼,並且更簡潔。例如,它不依賴於 LDAP 或 servlet API,並且現在有單獨的 jar 用於 Web 特定代碼和 LDAP。我們還將命名空間剖析代碼拆分為單獨的 jar,因為它依賴於大多數其他 jar,並且不公開您可能直接在應用程式中使用的任何公用 API。只有在使用應用程式上下文 XML 檔案中的 Spring Security 命名空間組態時,才需要使用它。主要專案 jar 如下表所示。
Jar 名稱 描述 何時使用 根套件
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(及其傳遞依賴項)。這也使代碼更易於導航和理解。Spring Security 3.0 jar 之間的依賴關係,這些 jar 現在構成了我們在上面針對 2.0.4 版本看到的相同代碼集,如下所示
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 套件和子套件包含框架中使用的基本類別和介面,核心 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 中,這些已被兩個獨立的策略取代AuthenticationSuccessHandlerAuthenticationFailureHandler,它們完全負責處理目的地。查看這些介面的 Javadoc,並查看問題 SEC-745 以取得更多資訊。

參考手冊和網站更新

顯然,3.0 參考手冊仍然是一個正在進行中的工作 :-),但我們一直在進行一些更新。命名空間技術概述 章節應提供框架的合理概述。請隨時透過問題追蹤器提交任何想法或補丁。同樣,如果您發現任何錯誤,當然。

專案網站也已更新。常見問題解答有一些新問題,並且有一個新頁面包含指向簡報影片和線上文章的連結。請看看並告訴我們您想在那裡看到什麼(外部安全連結頁面已經在工作中)。

結論

Spring Security 3 仍有很多工作要做,但我們希望您能試用此里程碑版本,並提供有關新表達式語言支援的一些回饋。您可以在 Jira 變更日誌中找到迄今為止的完整變更清單,並且您還可以在那裡找到指向目前專案路線圖的連結。

社群論壇是詢問有關使用 Spring Security 的問題或開始討論新功能的最佳場所。或者,如果您發現任何問題,您可以提出 Jira 問題

我們希望您喜歡使用 Spring Security

取得 Spring 電子報

隨時掌握 Spring 電子報的最新消息

訂閱