安全名稱空間配置

名稱空間配置自 Spring Framework 2.0 版以來一直可用。它允許您使用額外 XML 模式中的元素補充傳統的 Spring bean 應用程式上下文語法。您可以在 Spring 參考文件中找到更多資訊。您可以使用名稱空間元素更簡潔地配置單個 bean,或者更強大地,定義一種更符合問題領域並向用戶隱藏底層複雜性的替代配置語法。一個簡單的元素可以隱藏將多個 bean 和處理步驟新增到應用程式上下文的事實。例如,將以下來自 security 名稱空間的元素新增到應用程式上下文會啟動一個嵌入式 LDAP 伺服器,供應用程式內測試使用

<security:ldap-server />

這比連線等效的 UnboundID 伺服器 bean 簡單得多。最常見的替代配置要求由 ldap-server 元素上的屬性支援,使用者無需擔心需要建立哪些 bean 以及 bean 屬性名稱是什麼。您可以在關於 LDAP 認證的章節中找到有關 ldap-server 元素使用的更多資訊。一個好的 XML 編輯器在編輯應用程式上下文檔案時應該提供有關可用屬性和元素的資訊。我們建議您嘗試 Spring Tool Suite,因為它具有處理標準 Spring 名稱空間的特殊功能。

要開始在應用程式上下文中使用 security 名稱空間,請將 spring-security-config jar 新增到您的類路徑。然後,您只需將模式宣告新增到您的應用程式上下文檔案

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security
		https://www.springframework.org/schema/security/spring-security.xsd">
	...
</beans>

在許多您可以看到的示例(以及示例應用程式)中,我們通常使用 security(而不是 beans)作為預設名稱空間,這意味著我們可以省略所有安全名稱空間元素上的字首,使內容更易於閱讀。如果您將應用程式上下文分為單獨的檔案,並且將大部分安全配置放在其中一個檔案中,您可能也想這樣做。您的安全應用程式上下文檔案將以這種方式開始

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security
		https://www.springframework.org/schema/security/spring-security.xsd">
	...
</beans:beans>

在本章中,我們假設從現在開始使用此語法。

名稱空間設計

該名稱空間旨在捕獲框架最常見的用途,並提供簡化且簡潔的語法以在應用程式中啟用它們。該設計基於框架內部的大規模依賴關係,可分為以下幾個領域

  • Web/HTTP 安全 是最複雜的部分。它設定過濾器和相關的服務 bean,用於應用框架認證機制、保護 URL、渲染登入和錯誤頁面等等。

  • 業務物件(方法)安全 定義了保護服務層的選項。

  • AuthenticationManager 處理來自框架其他部分的認證請求。

  • AccessDecisionManager 為 Web 和方法安全提供訪問決策。預設的管理器已註冊,但您可以選擇使用自定義管理器,使用普通 Spring bean 語法宣告。

  • AuthenticationProvider 例項提供認證管理器用於認證使用者的機制。名稱空間支援幾種標準選項以及新增使用傳統語法宣告的自定義 bean 的方法。

  • UserDetailsService 與認證提供者密切相關,但通常也為其他 bean 所需。

我們將在以下各節中介紹如何配置這些內容。

Spring Security 名稱空間配置入門

本節將介紹如何構建名稱空間配置以使用框架的一些主要功能。我們假設您最初希望儘快啟動並執行,並向現有 Web 應用程式新增身份驗證支援和訪問控制,並進行一些測試登入。然後,我們將研究如何切換到針對資料庫或其他安全儲存庫進行身份驗證。在後面的部分中,我們將介紹更高階的名稱空間配置選項。

web.xml 配置

您需要做的第一件事是將以下過濾器宣告新增到您的 web.xml 檔案中

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

DelegatingFilterProxy 是一個 Spring Framework 類,它將請求委託給在應用程式上下文中定義為 Spring bean 的過濾器實現。在這種情況下,該 bean 名為 springSecurityFilterChain,它是由名稱空間建立的一個內部基礎設施 bean,用於處理 Web 安全。在這種情況下,該 bean 名為“springSecurityFilterChain”,它是名稱空間建立的用於處理 Web 安全的內部基礎設施 bean。請注意,您不應自行使用此 bean 名稱。將此 bean 新增到 web.xml 後,您就可以開始編輯應用程式上下文檔案了。Web 安全服務由 <http> 元素配置。

最小 <http> 配置

要啟用 Web 安全,您需要以下配置

<http>
<intercept-url pattern="/**" access="hasRole('USER')" />
<form-login />
<logout />
</http>

該列表表示我們希望

  • 我們應用程式中的所有 URL 都受到保護,需要 ROLE_USER 角色才能訪問它們

  • 使用帶有使用者名稱和密碼的表單登入到應用程式

  • 註冊一個登出 URL,允許我們登出應用程式

<http> 元素是所有與 Web 相關名稱空間功能的父級。<intercept-url> 元素定義一個 pattern,該模式使用 Ant 路徑語法與傳入請求的 URL 進行匹配。有關如何實際執行匹配的更多詳細資訊,請參閱關於 HttpFirewall 的部分。您也可以使用正則表示式匹配作為替代(有關更多詳細資訊,請參閱名稱空間附錄)。access 屬性定義了與給定模式匹配的請求的訪問要求。使用預設配置,這通常是一個逗號分隔的角色列表,使用者必須擁有其中一個角色才能被允許發出請求。ROLE_ 字首是一個標記,指示應與使用者的許可權進行簡單比較。換句話說,應使用正常的基於角色的檢查。Spring Security 中的訪問控制不限於使用簡單角色(因此使用字首來區分不同型別的安全屬性)。我們稍後會看到解釋如何變化。access 屬性中逗號分隔值的解釋取決於使用哪個 AccessDecisionManager 實現。自 Spring Security 3.0 起,您還可以使用 EL 表示式填充該屬性。

您可以使用多個 <intercept-url> 元素來為不同的 URL 集定義不同的訪問要求,但它們按列出的順序進行評估,並使用第一個匹配項。因此,您必須將最具體的匹配項放在頂部。您還可以新增一個 method 屬性,將匹配限制為特定的 HTTP 方法(GETPOSTPUT 等)。

要新增使用者,您可以直接在名稱空間中定義一組測試資料

<authentication-manager>
<authentication-provider>
	<user-service>
	<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
	NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
	in samples easier. Normally passwords should be hashed using BCrypt -->
	<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
	</user-service>
</authentication-provider>
</authentication-manager>

前面的列表展示了一個安全儲存相同密碼的示例。密碼以 {bcrypt} 為字首,以指示 DelegatingPasswordEncoder(它支援任何配置的 PasswordEncoder 進行匹配)密碼使用 BCrypt 進行雜湊

<authentication-manager>
<authentication-provider>
	<user-service>
	<user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
			authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
			authorities="ROLE_USER" />
	<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
	</user-service>
</authentication-provider>
</authentication-manager>

<http> 元素負責建立 FilterChainProxy 及其使用的過濾器 bean。以前常見的問題(例如不正確的過濾器順序)不再是問題,因為過濾器位置是預定義的。

<authentication-provider> 元素建立一個 DaoAuthenticationProvider bean,而 <user-service> 元素建立一個 InMemoryDaoImpl。所有 authentication-provider 元素都必須是 <authentication-manager> 元素的子元素,該元素建立一個 ProviderManager 並向其註冊認證提供者。您可以在名稱空間附錄中找到有關建立的 bean 的更詳細資訊。如果您想開始瞭解框架中的重要類及其使用方式,特別是如果您想以後自定義事物,則應交叉檢查此附錄。

前面的配置定義了兩個使用者、他們的密碼以及他們在應用程式中的角色(用於訪問控制)。您還可以透過設定 user-service 元素上的 properties 屬性,從標準屬性檔案中載入使用者資訊。有關檔案格式的更多詳細資訊,請參閱關於記憶體認證的部分。使用 <authentication-provider> 元素意味著使用者管理器將使用使用者資訊來處理認證請求。您可以有多個 <authentication-provider> 元素來定義不同的認證源。每個都依次被諮詢。

此時,您應該能夠啟動應用程式,並且需要登入才能繼續。嘗試一下,或者嘗試使用專案隨附的“教程”示例應用程式。

設定預設的登入後目標

如果表單登入不是由嘗試訪問受保護資源而觸發的,則 default-target-url 選項會發揮作用。這是使用者成功登入後跳轉的 URL,預設值為 /。您還可以透過將 always-use-default-target 屬性設定為 true 來配置,使戶總是跳轉到此頁面(無論登入是“按需”還是他們明確選擇登入)。例如,如果您的應用程式總是要求使用者從“主頁”開始,這將非常有用

<http pattern="/login.htm*" security="none"/>
<http use-expressions="false">
<intercept-url pattern='/**' access='ROLE_USER' />
<form-login login-page='/login.htm' default-target-url='/home.htm'
		always-use-default-target='true' />
</http>

為了更精確地控制目標,您可以使用 authentication-success-handler-ref 屬性來替代 default-target-url。引用的 bean 應該是 AuthenticationSuccessHandler 的一個例項。

高階 Web 功能

本節介紹超出基礎知識的各種功能。

新增您自己的過濾器

如果您以前使用過 Spring Security,您就會知道該框架維護著一個用於應用其服務的過濾器鏈。您可能希望在特定位置向堆疊新增自己的過濾器,或者使用當前沒有名稱空間配置選項的 Spring Security 過濾器(例如 CAS)。另外,您可能希望使用標準名稱空間過濾器的定製版本,例如 UsernamePasswordAuthenticationFilter(由 <form-login> 元素建立),以利用顯式使用 bean 時可用的一些額外配置選項。如何使用名稱空間配置來實現這一點,因為過濾器鏈沒有直接公開?

使用名稱空間時,過濾器的順序始終嚴格執行。當應用程式上下文建立時,過濾器 bean 由名稱空間處理程式碼排序,並且標準 Spring Security 過濾器在名稱空間中都有一個別名和眾所周知的位置。

在早期版本中,排序發生在過濾器例項建立之後,即應用程式上下文的後處理期間。在 3.0+ 版本中,排序現在在 bean 元資料級別完成,在類例項化之前。這對於您如何將自己的過濾器新增到堆疊中具有影響,因為在解析 <http> 元素期間必須知道整個過濾器列表,因此語法在 3.0 中略有更改。

以下表格顯示了過濾器、別名以及建立這些過濾器的名稱空間元素和屬性,按它們在過濾器鏈中出現的順序排列

表 1. 標準過濾器別名和順序
別名 過濾器類 名稱空間元素或屬性

DISABLE_ENCODE_URL_FILTER

DisableEncodeUrlFilter

http@disable-url-rewriting

FORCE_EAGER_SESSION_FILTER

ForceEagerSessionCreationFilter

http@create-session="ALWAYS"

CHANNEL_FILTER

ChannelProcessingFilter

http/intercept-url@requires-channel

SECURITY_CONTEXT_FILTER

SecurityContextPersistenceFilter

http

CONCURRENT_SESSION_FILTER

ConcurrentSessionFilter

session-management/concurrency-control

HEADERS_FILTER

HeaderWriterFilter

http/headers

CSRF_FILTER

CsrfFilter

http/csrf

LOGOUT_FILTER

LogoutFilter

http/logout

X509_FILTER

X509AuthenticationFilter

http/x509

PRE_AUTH_FILTER

AbstractPreAuthenticatedProcessingFilter 子類

不適用

CAS_FILTER

CasAuthenticationFilter

不適用

FORM_LOGIN_FILTER

UsernamePasswordAuthenticationFilter

http/form-login

BASIC_AUTH_FILTER

BasicAuthenticationFilter

http/http-basic

SERVLET_API_SUPPORT_FILTER

SecurityContextHolderAwareRequestFilter

http/@servlet-api-provision

JAAS_API_SUPPORT_FILTER

JaasApiIntegrationFilter

http/@jaas-api-provision

REMEMBER_ME_FILTER

RememberMeAuthenticationFilter

http/remember-me

ANONYMOUS_FILTER

AnonymousAuthenticationFilter

http/anonymous

SESSION_MANAGEMENT_FILTER

SessionManagementFilter

session-management

EXCEPTION_TRANSLATION_FILTER

ExceptionTranslationFilter

http

FILTER_SECURITY_INTERCEPTOR

FilterSecurityInterceptor

http

SWITCH_USER_FILTER

SwitchUserFilter

不適用

您可以使用 custom-filter 元素和其中一個名稱來指定過濾器在堆疊中出現的位置,從而將自己的過濾器新增到堆疊中

<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>

<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>

如果您希望將過濾器插入堆疊中另一個過濾器之前或之後,您也可以使用 afterbefore 屬性。您可以將 FIRSTLASTposition 屬性一起使用,分別表示您希望過濾器出現在整個堆疊之前或之後。

避免過濾器位置衝突

如果您插入的自定義過濾器可能與名稱空間建立的標準過濾器之一佔據相同的位置,您不應錯誤地包含名稱空間版本。刪除任何建立您要替換其功能的過濾器的元素。

請注意,您不能替換由 <http> 元素本身建立的過濾器:SecurityContextPersistenceFilterExceptionTranslationFilterFilterSecurityInterceptor。預設情況下,會新增一個 AnonymousAuthenticationFilter,除非您停用了會話固定保護,否則還會將一個 SessionManagementFilter 新增到過濾器鏈中。

如果您替換需要認證入口點(即,認證過程由未經認證的使用者嘗試訪問受保護資源觸發)的名稱空間過濾器,您還需要新增一個自定義入口點 bean。

方法安全

自 2.0 版本以來,Spring Security 對為服務層方法新增安全性提供了 substantial 支援。它支援 JSR-250 註解安全以及框架最初的 @Secured 註解。自 3.0 版本以來,您還可以使用基於表示式的註解。您可以將安全性應用於單個 bean(透過使用 intercept-methods 元素修飾 bean 宣告),也可以使用 AspectJ 樣式切入點來保護整個服務層中的多個 bean。

預設的 AccessDecisionManager

本節假設您對 Spring Security 中訪問控制的底層架構有一些瞭解。如果您不瞭解,可以跳過本節稍後再返回,因為本節僅與需要進行一些自定義以使用更簡單的基於角色的安全之外的人員相關。

當您使用名稱空間配置時,會自動為您註冊 AccessDecisionManager 的預設例項,並根據您在 intercept-urlprotect-pointcut 宣告中(以及在註解中,如果您使用註解來保護方法)指定的訪問屬性,用於對方法呼叫和 Web URL 訪問做出訪問決策。

預設策略是使用帶有 RoleVoterAuthenticatedVoterAffirmativeBased AccessDecisionManager。您可以在關於授權的章節中瞭解更多資訊。

自定義 AccessDecisionManager

如果您需要使用更復雜的訪問控制策略,可以為方法和 Web 安全設定替代方案。

對於方法安全,您可以透過將 global-method-security 上的 access-decision-manager-ref 屬性設定為應用程式上下文中相應 AccessDecisionManager bean 的 id 來實現

<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
...
</global-method-security>

Web 安全的語法相同,但屬性位於 http 元素上

<http access-decision-manager-ref="myAccessDecisionManagerBean">
...
</http>
© . This site is unofficial and not affiliated with VMware.