Java 驗證與授權服務 (JAAS) 提供者
Spring Security 提供一個套件,將驗證請求委派給 Java 驗證與授權服務 (JAAS)。本節將討論該套件。
AbstractJaasAuthenticationProvider
AbstractJaasAuthenticationProvider
類別是所提供的 JAAS AuthenticationProvider
實作的基礎。子類別必須實作一個方法來建立 LoginContext
。AbstractJaasAuthenticationProvider
有許多依賴項可以注入其中,如本節的其餘部分所述。
JAAS CallbackHandler
大多數 JAAS LoginModule
實例都需要某種形式的回呼。這些回呼通常用於從使用者取得使用者名稱和密碼。
在 Spring Security 部署中,Spring Security 負責此使用者互動(透過驗證機制)。因此,當驗證請求委派給 JAAS 時,Spring Security 的驗證機制已經完全填充了一個 Authentication
物件,其中包含 JAAS LoginModule
所需的所有資訊。
因此,Spring Security 的 JAAS 套件提供了兩個預設的回呼處理器:JaasNameCallbackHandler
和 JaasPasswordCallbackHandler
。每個回呼處理器都實作了 JaasAuthenticationCallbackHandler
。在大多數情況下,可以使用這些回呼處理器,而無需了解其內部機制。
對於需要完全控制回呼行為的使用者,AbstractJaasAuthenticationProvider
在內部使用 InternalCallbackHandler
包裝這些 JaasAuthenticationCallbackHandler
實例。InternalCallbackHandler
是實際實作 JAAS 標準 CallbackHandler
介面的類別。任何時候使用 JAAS LoginModule
時,都會將已組態的應用程式內容 InternalCallbackHandler
實例列表傳遞給它。如果 LoginModule
針對 InternalCallbackHandler
實例請求回呼,則回呼會依序傳遞給正在包裝的 JaasAuthenticationCallbackHandler
實例。
JAAS AuthorityGranter
JAAS 使用 Principal。即使是「角色」在 JAAS 中也表示為 Principal。另一方面,Spring Security 使用 Authentication
物件。每個 Authentication
物件都包含單一 Principal 和多個 GrantedAuthority
實例。為了促進這些不同概念之間的對應,Spring Security 的 JAAS 套件包含一個 AuthorityGranter
介面。
AuthorityGranter
負責檢查 JAAS Principal 並傳回一組 String
物件,這些物件代表指派給 Principal 的權限。對於每個傳回的權限字串,AbstractJaasAuthenticationProvider
會建立一個 JaasGrantedAuthority
(實作 Spring Security 的 GrantedAuthority
介面),其中包含權限字串和 AuthorityGranter
傳遞的 JAAS Principal。AbstractJaasAuthenticationProvider
透過首先使用 JAAS LoginModule
成功驗證使用者的憑證,然後存取它傳回的 LoginContext
來取得 JAAS Principal。呼叫 LoginContext.getSubject().getPrincipals()
,並將每個產生的 Principal 傳遞給針對 AbstractJaasAuthenticationProvider.setAuthorityGranters(List)
屬性定義的每個 AuthorityGranter
。
Spring Security 不包含任何生產環境的 AuthorityGranter
實例,因為每個 JAAS Principal 都有實作特定的意義。但是,單元測試中有一个 TestAuthorityGranter
,它示範了簡單的 AuthorityGranter
實作。
DefaultJaasAuthenticationProvider
DefaultJaasAuthenticationProvider
允許將 JAAS Configuration
物件作為依賴項注入其中。然後,它使用注入的 JAAS Configuration
建立 LoginContext
。這表示 DefaultJaasAuthenticationProvider
不會繫結到任何特定的 Configuration
實作,就像 JaasAuthenticationProvider
一樣。
InMemoryConfiguration
為了讓將 Configuration
注入到 DefaultJaasAuthenticationProvider
變得容易,提供了一個名為 InMemoryConfiguration
的預設記憶體實作。實作建構子接受一個 Map
,其中每個鍵代表登入組態名稱,而值代表 AppConfigurationEntry
實例的 Array
。如果提供的 Map
中找不到對應項,InMemoryConfiguration
也支援預設的 AppConfigurationEntry
物件 Array
。如需詳細資訊,請參閱 InMemoryConfiguration
的 Javadoc。
DefaultJaasAuthenticationProvider 範例組態
雖然 InMemoryConfiguration
的 Spring 組態可能比標準 JAAS 組態檔更冗長,但在與 DefaultJaasAuthenticationProvider
結合使用時,比 JaasAuthenticationProvider
更具彈性,因為它不依賴預設的 Configuration
實作。
下一個範例提供了 DefaultJaasAuthenticationProvider
的組態,它使用 InMemoryConfiguration
。請注意,自訂的 Configuration
實作也可以輕鬆地注入到 DefaultJaasAuthenticationProvider
中。
<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<map>
<!--
SPRINGSECURITY is the default loginContextName
for AbstractJaasAuthenticationProvider
-->
<entry key="SPRINGSECURITY">
<array>
<bean class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg value="sample.SampleLoginModule" />
<constructor-arg>
<util:constant static-field=
"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
</constructor-arg>
<constructor-arg>
<map></map>
</constructor-arg>
</bean>
</array>
</entry>
</map>
</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
<!-- You will need to write your own implementation of AuthorityGranter -->
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
JaasAuthenticationProvider
JaasAuthenticationProvider
假設預設的 Configuration
是 ConfigFile
的實例。做出此假設是為了嘗試更新 Configuration
。然後,JaasAuthenticationProvider
使用預設的 Configuration
來建立 LoginContext
。
假設我們有一個 JAAS 登入組態檔 /WEB-INF/login.conf
,其內容如下
JAASTest {
sample.SampleLoginModule required;
};
與所有 Spring Security Bean 一樣,JaasAuthenticationProvider
是透過應用程式內容進行組態的。以下定義將對應於上述 JAAS 登入組態檔
<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<property name="loginContextName" value="JAASTest"/>
<property name="callbackHandlers">
<list>
<bean
class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<bean
class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</list>
</property>
<property name="authorityGranters">
<list>
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
以 Subject 身份執行
如果已組態,JaasApiIntegrationFilter
會嘗試以 JaasAuthenticationToken
上的 Subject
身份執行。這表示可以使用以下方式存取 Subject
Subject subject = Subject.getSubject(AccessController.getContext());
您可以使用 jaas-api-provision 屬性來組態此整合。當與依賴 JAAS Subject 已填充的舊版或外部 API 整合時,此功能非常有用。