跳到主要内容
版本:6.4.3

Java 认证与授权服务 (JAAS) 提供者

QWen Max 中英对照 JAAS Java Authentication and Authorization Service (JAAS) Provider

Spring Security 提供了一个包,用于将认证请求委托给 Java 认证和授权服务 (JAAS)。本节将讨论该包。

AbstractJaasAuthenticationProvider​

AbstractJaasAuthenticationProvider 类是所提供的 JAAS AuthenticationProvider 实现的基础。子类必须实现一个创建 LoginContext 的方法。AbstractJaasAuthenticationProvider 有许多可以注入的依赖项,本节的其余部分将对此进行讨论。

JAAS CallbackHandler​

大多数 JAAS LoginModule 实例都需要某种形式的回调。这些回调通常用于从用户那里获取用户名和密码。

在 Spring Security 部署中,Spring Security 负责这种用户交互(通过认证机制)。因此,在认证请求被委派给 JAAS 时,Spring Security 的认证机制已经完全填充了一个包含 JAAS LoginModule 所需所有信息的 Authentication 对象。

因此,Spring Security 的 JAAS 包提供了两个默认的回调处理器:JaasNameCallbackHandler 和 JaasPasswordCallbackHandler。这些回调处理器各自实现了 JaasAuthenticationCallbackHandler。在大多数情况下,可以使用这些回调处理器而无需了解其内部机制。

对于那些需要完全控制回调行为的用户,AbstractJaasAuthenticationProvider 内部将这些 JaasAuthenticationCallbackHandler 实例用一个 InternalCallbackHandler 包装起来。InternalCallbackHandler 是实际实现 JAAS 标准 CallbackHandler 接口的类。每当使用 JAAS LoginModule 时,都会传递一个应用程序上下文中配置的 InternalCallbackHandler 实例列表。如果 LoginModule 请求对 InternalCallbackHandler 实例进行回调,则该回调会依次传递给被包装的 JaasAuthenticationCallbackHandler 实例。

JAAS AuthorityGranter​

JAAS 与主体(principals)一起工作。甚至“角色”在 JAAS 中也表示为主体。另一方面,Spring Security 则使用 Authentication 对象。每个 Authentication 对象包含一个单独的主体和多个 GrantedAuthority 实例。为了便于在这些不同概念之间进行映射,Spring Security 的 JAAS 包含了一个 AuthorityGranter 接口。

AuthorityGranter 负责检查 JAAS 主体并返回一组表示分配给该主体的权限的 String 对象。对于每个返回的权限字符串,AbstractJaasAuthenticationProvider 会创建一个包含该权限字符串和传递给 AuthorityGranter 的 JAAS 主体的 JaasGrantedAuthority(它实现了 Spring Security 的 GrantedAuthority 接口)。AbstractJaasAuthenticationProvider 通过首先使用 JAAS LoginModule 成功验证用户的凭据,然后访问其返回的 LoginContext 来获取 JAAS 主体。调用 LoginContext.getSubject().getPrincipals(),并将每个结果主体传递给在 AbstractJaasAuthenticationProvider.setAuthorityGranters(List) 属性中定义的每个 AuthorityGranter。

Spring Security 没有包含任何生产环境的 AuthorityGranter 实例,因为每个 JAAS 主体都有特定于实现的含义。不过,在单元测试中有一个 TestAuthorityGranter,它展示了一个简单的 AuthorityGranter 实现。

DefaultJaasAuthenticationProvider​

DefaultJaasAuthenticationProvider 允许将 JAAS Configuration 对象作为依赖项注入到其中。然后,它通过使用注入的 JAAS Configuration 来创建一个 LoginContext。这意味着 DefaultJaasAuthenticationProvider 不绑定到任何特定的 Configuration 实现,而 JaasAuthenticationProvider 则是绑定的。

InMemoryConfiguration​

为了方便将 Configuration 注入到 DefaultJaasAuthenticationProvider 中,提供了一个默认的内存实现,名为 InMemoryConfiguration。该实现的构造函数接受一个 Map,其中每个键表示一个登录配置名称,值表示 AppConfigurationEntry 实例的 Array。InMemoryConfiguration 还支持一个默认的 AppConfigurationEntry 对象的 Array,如果在提供的 Map 中找不到映射,则使用该默认数组。有关详细信息,请参阅 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>

以主体身份运行​

如果已配置,JaasApiIntegrationFilter 会尝试以 JaasAuthenticationToken 上的 Subject 身份运行。这意味着可以使用以下方式访问 Subject:

Subject subject = Subject.getSubject(AccessController.getContext());

您可以使用 jaas-api-provision 属性来配置此集成。当与依赖于 JAAS Subject 被填充的遗留或外部 API 集成时,此功能非常有用。