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 會將這些 JaasAuthenticationCallbackHandler 例項內部包裝在一個 InternalCallbackHandler 中。InternalCallbackHandler 是實際實現 JAAS 標準 CallbackHandler 介面的類。無論何時使用 JAAS LoginModule,都會向其傳遞一個配置好的 InternalCallbackHandler 例項的應用上下文列表。如果 LoginModule 請求針對 InternalCallbackHandler 例項的回撥,則回撥會依次傳遞給被包裝的 JaasAuthenticationCallbackHandler 例項。
JAAS AuthorityGranter
JAAS 使用主體。即使“角色”在 JAAS 中也表示為主體。而 Spring Security 則使用 Authentication 物件。每個 Authentication 物件包含一個主體和多個 GrantedAuthority 例項。為了便於在這些不同概念之間進行對映,Spring Security 的 JAAS 包包含一個 AuthorityGranter 介面。
AuthorityGranter 負責檢查 JAAS 主體並返回一組表示分配給該主體的許可權的 String 物件。對於每個返回的許可權字串,AbstractJaasAuthenticationProvider 會建立一個 JaasGrantedAuthority(它實現了 Spring Security 的 GrantedAuthority 介面),其中包含許可權字串和傳遞給 AuthorityGranter 的 JAAS 主體。AbstractJaasAuthenticationProvider 首先透過使用 JAAS LoginModule 成功認證使用者的憑據,然後訪問其返回的 LoginContext 來獲取 JAAS 主體。呼叫 LoginContext.getSubject().getPrincipals(),並將每個結果主體傳遞給 AbstractJaasAuthenticationProvider.setAuthorityGranters(List) 屬性中定義的每個 AuthorityGranter。
鑑於每個 JAAS 主體都具有特定於實現的含義,Spring Security 不包含任何生產 AuthorityGranter 例項。但是,當認證成功時,Spring Security 預設會發出 FACTOR_PASSWORD 許可權。
|
單元測試中有一個 |
DefaultJaasAuthenticationProvider
DefaultJaasAuthenticationProvider 允許將 JAAS Configuration 物件作為依賴項注入其中。然後,它使用注入的 JAAS Configuration 建立一個 LoginContext。這意味著 DefaultJaasAuthenticationProvider 不受任何特定的 Configuration 實現的約束,而 JaasAuthenticationProvider 則受其約束。
InMemoryConfiguration
為了方便將 Configuration 注入 DefaultJaasAuthenticationProvider,提供了一個名為 InMemoryConfiguration 的預設記憶體實現。該實現建構函式接受一個 Map,其中每個鍵表示一個登入配置名稱,值表示一個 AppConfigurationEntry 例項的 Array。InMemoryConfiguration 還支援一個預設的 AppConfigurationEntry 物件 Array,如果在提供的 Map 中找不到對映,則使用該 Array。有關詳細資訊,請參閱 InMemoryConfiguration 的 Javadoc。
DefaultJaasAuthenticationProvider 示例配置
儘管 InMemoryConfiguration 的 Spring 配置可能比標準的 JAAS 配置檔案更冗長,但將其與 DefaultJaasAuthenticationProvider 結合使用比 JaasAuthenticationProvider 更靈活,因為它不依賴於預設的 Configuration 實現。
下一個示例提供了使用 InMemoryConfiguration 的 DefaultJaasAuthenticationProvider 配置。請注意,自定義的 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 整合時,此功能非常有用。