# Java 身份验证和授权服务提供者

# 概述

Spring 安全性提供了一种包,能够将身份验证请求委托给 Java 身份验证和授权服务。下面将详细讨论这个包。

# 抽象 JaasAuthenticationProvider

AbstractJaasAuthenticationProvider是所提供的 JAASAuthenticationProvider实现的基础。子类必须实现创建LoginContext的方法。AbstractJaasAuthenticationProvider具有许多可以注入其中的依赖项,这些依赖项将在下面讨论。

# JAAS CallbackHandler

大多数 JAASLoginModules 都需要某种类型的回调。这些回调通常用于从用户获得用户名和密码。

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

因此, Spring Security 的 JAAS 包提供了两个默认的回调处理程序,JaasNameCallbackHandlerJaasPasswordCallbackHandler。这些回调处理程序中的每一个都实现JaasAuthenticationCallbackHandler。在大多数情况下,这些回调处理程序可以在不了解内部机制的情况下简单地使用。

对于那些需要完全控制回调行为的人,内部AbstractJaasAuthenticationProvider将这些JaasAuthenticationCallbackHandlers 包装成InternalCallbackHandlerInternalCallbackHandler是实际实现 JAASNormalCallbackHandler接口的类。每当使用 JAASLoginModule时,都会传递一个配置InternalCallbackHandlers 的应用程序上下文列表。如果LoginModuleInternalCallbackHandlers 请求回调,则回调依次传递给正在打包的JaasAuthenticationCallbackHandlers。

# Jaas AuthorityGranter

JAAS 与校长一起工作。在 JAAS 中,甚至连“角色”也被表示为主体。 Spring 另一方面,安全性适用于Authentication对象。每个Authentication对象包含一个主体,以及多个GrantedAuthoritys。为了便于在这些不同概念之间进行映射, Spring Security 的 JAAS 包包括一个AuthorityGranter接口。

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

Spring 考虑到每个 JAAS 主体都具有特定于实现的含义,安全性不包括任何AuthorityGranters 的产品。然而,在单元测试中有一个TestAuthorityGranter演示了一个简单的AuthorityGranter实现。

# DefaultJaasAuthenticationProvider

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

# 记忆组态

为了方便地将Configuration注入DefaultJaasAuthenticationProvider,提供了一个名为InMemoryConfiguration的默认内存中实现。实现构造函数接受一个Map,其中每个键表示一个登录配置名,该值表示ArrayAppConfigurationEntrys。InMemoryConfiguration还支持一个Array的缺省ArrayAppConfigurationEntry对象,如果在提供的Map中找不到映射,则将使用该对象。有关详细信息,请参阅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假设默认的Configuration配置文件 (opens new window)的实例。这个假设是为了尝试更新Configuration。然后JaasAuthenticationProvider使用默认的Configuration来创建LoginContext

假设我们有一个 JAAS 登录配置文件/WEB-INF/login.conf,其内容如下:

JAASTest {
	sample.SampleLoginModule required;
};

与所有 Spring 安全 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-供应属性轻松配置此集成。当与依赖于填充的 JAAS 主题的遗留或外部 API 集成时,此功能非常有用。

预先认证CAS