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 包提供了两个默认回调处理程序:JaasNameCallbackHandler
和 JaasPasswordCallbackHandler
。这两个回调处理程序都实现了 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 主体都有一个特定于实现的含义。但是,单元测试中有一个 TestAuthorityGranter
,它演示了一个简单的 AuthorityGranter
实现。
默认 JaasAuthenticationProvider
DefaultJaasAuthenticationProvider
允许将 JAAS Configuration
对象作为依赖项注入到其中。然后,它使用注入的 JAAS Configuration
创建一个 LoginContext
。这意味着 DefaultJaasAuthenticationProvider
不绑定到 Configuration
的任何特定实现,就像 JaasAuthenticationProvider
一样。
内存中配置
为了便于将 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>
以主体身份运行
如果已配置,JaasApiIntegrationFilter
将尝试以 JaasAuthenticationToken
上的 Subject
身份运行。这意味着可以使用以下方法访问 Subject
Subject subject = Subject.getSubject(AccessController.getContext());
可以使用 jaas-api-provision 属性配置此集成。当与依赖于 JAAS Subject 填充的遗留或外部 API 集成时,此功能很有用。