Java 身份验证和授权服务 (JAAS) 提供程序

Spring Security 提供了一个包来将身份验证请求委托给 Java 身份验证和授权服务 (JAAS)。本节讨论该包。

AbstractJaasAuthenticationProvider

AbstractJaasAuthenticationProvider 类是提供的 JAAS AuthenticationProvider 实现的基础。子类必须实现一个创建 LoginContext 的方法。AbstractJaasAuthenticationProvider 有许多可以注入到其中的依赖项,如本节其余部分所述。

JAAS 回调处理器

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

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

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

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

JAAS 权限授予器

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

Spring Security 没有包含任何生产环境下的AuthorityGranter实例,因为每个 JAAS principal 都有其特定实现的含义。但是,单元测试中包含一个TestAuthorityGranter,它演示了一个简单的AuthorityGranter实现。

DefaultJaasAuthenticationProvider

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

InMemoryConfiguration

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

DefaultJaasAuthenticationProvider 示例配置

虽然InMemoryConfiguration的 Spring 配置可能比标准的 JAAS 配置文件更冗长,但将其与DefaultJaasAuthenticationProvider结合使用比JaasAuthenticationProvider更灵活,因为它不依赖于默认的Configuration实现。

下一个示例提供了一个使用InMemoryConfigurationDefaultJaasAuthenticationProvider配置。请注意,自定义的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 假设默认的ConfigurationConfigFile 的一个实例。做出此假设是为了尝试更新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 集成时,此功能非常有用。