|
此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Security 7.0.4! |
Java 认证和授权服务(JAAS)提供者
Spring Security 提供了一个包,用于将身份验证请求委托给 Java 身份验证和授权服务(JAAS)。 本节将讨论该包。
抽象 JAAS 认证提供者
AbstractJaasAuthenticationProvider 类是所提供的 JAAS AuthenticationProvider 实现的基础。
子类必须实现一个用于创建 LoginContext 的方法。
AbstractJaasAuthenticationProvider 具有多个依赖项,这些依赖项可被注入其中,如下文本节其余部分所述。
JAAS 回调处理器
大多数 JAAS LoginModule 实例都需要某种形式的回调。
这些回调通常用于从用户处获取用户名和密码。
在 Spring Security 的部署中,Spring Security 负责处理该用户交互(通过认证机制)。
因此,当认证请求被委托给 JAAS 时,Spring Security 的认证机制已经完全填充了一个包含 JAAS Authentication 所需全部信息的 LoginModule 对象。
因此,Spring Security 的 JAAS 包提供了两个默认的回调处理器:JaasNameCallbackHandler 和 JaasPasswordCallbackHandler。
这些回调处理器均实现了 JaasAuthenticationCallbackHandler 接口。
在大多数情况下,无需了解其内部机制即可直接使用这些回调处理器。
对于那些需要完全控制回调行为的人,AbstractJaasAuthenticationProvider 在内部将这些 JaasAuthenticationCallbackHandler 实例包装在一个 InternalCallbackHandler 中。
InternalCallbackHandler 是实际实现 JAAS 标准 CallbackHandler 接口的类。
每当使用 JAAS LoginModule 时,都会传入一个配置了 InternalCallbackHandler 实例的应用程序上下文列表。
如果 LoginModule 请求对 InternalCallbackHandler 实例进行回调,则该回调会依次传递给被包装的 JaasAuthenticationCallbackHandler 实例。
JAAS 权限授予器
JAAS 使用主体(Principal)进行工作。
在 JAAS 中,即使是“角色”也以主体的形式表示。
而 Spring Security 则使用 Authentication 对象。
每个 Authentication 对象包含一个单一的主体(principal)和多个 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 实现。
DefaultJaasAuthenticationProvider
DefaultJaasAuthenticationProvider 允许将一个 JAAS Configuration 对象作为依赖注入其中。
然后,它使用注入的 JAAS LoginContext 创建一个 Configuration。
这意味着 DefaultJaasAuthenticationProvider 不像 Configuration 那样绑定到任何特定的 JaasAuthenticationProvider 实现。
内存配置
为了便于将 Configuration 注入到 DefaultJaasAuthenticationProvider,系统提供了一个名为 InMemoryConfiguration 的默认内存实现。
该实现的构造函数接受一个 Map,其中每个键代表登录配置名称,而值则代表一组 AppConfigurationEntry 实例的 Array。
InMemoryConfiguration 还支持一个默认的 AppConfigurationEntry 对象 Array,如果在提供的 Map 中未找到映射,则将使用此默认值。
有关详细信息,请参阅 InMemoryConfiguration 的 Javadoc。
DefaultJaasAuthenticationProvider 示例配置
虽然 InMemoryConfiguration 的 Spring 配置可能比标准的 JAAS 配置文件更为冗长,但将其与 DefaultJaasAuthenticationProvider 结合使用时,相比 JaasAuthenticationProvider 更加灵活,因为它不依赖于默认的 Configuration 实现。
下一个示例展示了使用 DefaultJaasAuthenticationProvider 的 InMemoryConfiguration 配置。
请注意,自定义的 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>
JAAS 认证提供者
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 会尝试以 Subject 上的 JaasAuthenticationToken 身份运行。
这意味着可以使用以下方式访问 Subject:
Subject subject = Subject.getSubject(AccessController.getContext());
您可以通过使用 jaas-api-provision 属性来配置此集成。 当与依赖于 JAAS Subject 被填充的旧系统或外部 API 进行集成时,此功能非常有用。