Java Authentication and Authorization Service (JAAS) Provider
Spring Security 提供了一个将身份验证请求委托给 Java 身份验证和授权服务 (JAAS) 的包。本节将对该包进行讨论。
Spring Security provides a package to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This section discusses that package.
AbstractJaasAuthenticationProvider
AbstractJaasAuthenticationProvider
类是所提供的 JAAS AuthenticationProvider
实现的基础。子类必须实现一个创建 LoginContext
的方法。AbstractJaasAuthenticationProvider
具有多个依赖项,可以通过注入来处理,如本节余下部分中所述。
The AbstractJaasAuthenticationProvider
class is the basis for the provided JAAS AuthenticationProvider
implementations.
Subclasses must implement a method that creates the LoginContext
.
The AbstractJaasAuthenticationProvider
has a number of dependencies that can be injected into it, as discussed in the remainder of this section.
JAAS CallbackHandler
大多数 JAAS LoginModule
实例需要某种回调。这些回调通常用于从用户那里获取用户名和密码。
Most JAAS LoginModule
instances require a callback of some sort.
These callbacks are usually used to obtain the username and password from the user.
在 Spring Security 部署中,Spring Security 对此用户交互负责(通过身份验证机制)。因此,在身份验证请求通过 JAAS 委派时,Spring Security 的身份验证机制已经完全填充了一个 Authentication
对象,其中包含 JAAS LoginModule
所需的所有信息。
In a Spring Security deployment, Spring Security is responsible for this user interaction (through the authentication mechanism).
Thus, by the time the authentication request is delegated through to JAAS, Spring Security’s authentication mechanism has already fully populated an Authentication
object that contains all the information required by the JAAS LoginModule
.
因此,针对 Spring Security 的 JAAS 包提供了两个默认回调处理程序: JaasNameCallbackHandler
和 JaasPasswordCallbackHandler
。每个回调处理程序实现 JaasAuthenticationCallbackHandler
。在大多数情况下,这些回调处理程序可以使用,而不需要理解内部机制。
Therefore, the JAAS package for Spring Security provides two default callback handlers: JaasNameCallbackHandler
and JaasPasswordCallbackHandler
.
Each of these callback handlers implements JaasAuthenticationCallbackHandler
.
In most cases, these callback handlers can be used without understanding the internal mechanics.
对于需要完全控制回调行为的用户,AbstractJaasAuthenticationProvider
会使用 JaasAuthenticationCallbackHandler
实例对这些进行内部包装,然后使用 InternalCallbackHandler
。InternalCallbackHandler
是真正实现 JAAS 正常 CallbackHandler
接口的类。每次 JAAS LoginModule
使用时,都会向它传递一个已配置 InternalCallbackHandler
实例的应用程序上下文列表。如果 LoginModule
请求针对 InternalCallbackHandler
实例进行回调,则该回调会依次传递给正在包装的 JaasAuthenticationCallbackHandler
实例。
For those needing full control over the callback behavior, AbstractJaasAuthenticationProvider
internally wraps these JaasAuthenticationCallbackHandler
instances with an InternalCallbackHandler
.
The InternalCallbackHandler
is the class that actually implements the JAAS normal CallbackHandler
interface.
Any time that the JAAS LoginModule
is used, it is passed a list of application contexts configured InternalCallbackHandler
instances.
If the LoginModule
requests a callback against the InternalCallbackHandler
instances, the callback is, in turn, passed to the JaasAuthenticationCallbackHandler
instances being wrapped.
JAAS AuthorityGranter
JAAS 使用主体。甚至 “roles” 也表示为 JAAS 的主体。另一方面,Spring Security 使用 Authentication
对象。每个 Authentication
对象包含一个主体和多个 GrantedAuthority
实例。为了方便在这些不同的概念之间进行映射,Spring Security 的 JAAS 包包括一个 AuthorityGranter
接口。
JAAS works with principals.
Even “roles” are represented as principals in JAAS.
Spring Security, on the other hand, works with Authentication
objects.
Each Authentication
object contains a single principal and multiple GrantedAuthority
instances.
To facilitate mapping between these different concepts, Spring Security’s JAAS package includes an AuthorityGranter
interface.
AuthorityGranter
负责检查 JAAS 主体并返回一组 String
对象来表示分配给该主体的权限。对于每个返回的权限字符串,AbstractJaasAuthenticationProvider
创建一个 JaasGrantedAuthority
(它实现了 Spring Security 的 GrantedAuthority
接口),其中包含权限字符串以及 AuthorityGranter
传递的 JAAS 主体。AbstractJaasAuthenticationProvider
通过首先使用 JAAS LoginModule
成功验证用户的凭据,然后访问它所返回的 LoginContext
来获取 JAAS 主体。按照 AbstractJaasAuthenticationProvider.setAuthorityGranters(List)
属性所定义的每个 AuthorityGranter
,调用 LoginContext.getSubject().getPrincipals()
,然后将每个结果主体传递给每个 AuthorityGranter
。
An AuthorityGranter
is responsible for inspecting a JAAS principal and returning a set of String
objects that represent the authorities assigned to the principal.
For each returned authority string, the AbstractJaasAuthenticationProvider
creates a JaasGrantedAuthority
(which implements Spring Security’s GrantedAuthority
interface) that contains the authority string and the JAAS principal that the AuthorityGranter
was passed.
The AbstractJaasAuthenticationProvider
obtains the JAAS principals by first successfully authenticating the user’s credentials by using the JAAS LoginModule
and then accessing the LoginContext
it returns.
A call to LoginContext.getSubject().getPrincipals()
is made, with each resulting principal passed to each AuthorityGranter
defined against the AbstractJaasAuthenticationProvider.setAuthorityGranters(List)
property.
Spring Security 不包含任何生产 AuthorityGranter
实例,因为每个 JAAS 主体都有一个特定于实现的含义。但是,单元测试中有一个 TestAuthorityGranter
,演示了一个简单的 AuthorityGranter
实现。
Spring Security does not include any production AuthorityGranter
instances, given that every JAAS principal has an implementation-specific meaning.
However, there is a TestAuthorityGranter
in the unit tests that demonstrates a simple AuthorityGranter
implementation.
DefaultJaasAuthenticationProvider
DefaultJaasAuthenticationProvider
允许向它注入一个 JAAS Configuration
对象作为依赖项。然后它使用注入的 JAAS Configuration
创建一个 LoginContext
。这意味着 DefaultJaasAuthenticationProvider
并没有诸如 JaasAuthenticationProvider
一样绑定到 Configuration
的任何特定实现。
The DefaultJaasAuthenticationProvider
lets a JAAS Configuration
object be injected into it as a dependency.
It then creates a LoginContext
by using the injected JAAS Configuration
.
This means that DefaultJaasAuthenticationProvider
is not bound to any particular implementation of Configuration
, as JaasAuthenticationProvider
is.
InMemoryConfiguration
为了方便将 Configuration
注入到 DefaultJaasAuthenticationProvider
中,提供了名为 InMemoryConfiguration
的默认内存实现。实现构造函数接受一个 Map
,其中每个键代表一个登录配置名称,而值代表 AppConfigurationEntry
实例的 Array
。InMemoryConfiguration
还支持一个 AppConfigurationEntry
对象的默认 Array
,如果在所提供的 Map
中找不到任何映射,则将使用该对象。有关详细信息,请参阅 {security-api-url}org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.html[InMemoryConfiguration
的 Javadoc]。
To make it easy to inject a Configuration
into DefaultJaasAuthenticationProvider
, a default in-memory implementation named InMemoryConfiguration
is provided.
The implementation constructor accepts a Map
where each key represents a login configuration name, and the value represents an Array
of AppConfigurationEntry
instances.
InMemoryConfiguration
also supports a default Array
of AppConfigurationEntry
objects that is used if no mapping is found within the provided Map
.
For details, see the {security-api-url}org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.html[Javadoc of InMemoryConfiguration
].
DefaultJaasAuthenticationProvider Example Configuration
虽然针对 InMemoryConfiguration
的 Spring 配置可能会比标准 JAAS 配置文件更加冗长,但将其与 DefaultJaasAuthenticationProvider
结合使用要比 JaasAuthenticationProvider
更加灵活,因为它不依赖于默认 Configuration
实现。
While the Spring configuration for InMemoryConfiguration
can be more verbose than the standard JAAS configuration files, using it in conjunction with DefaultJaasAuthenticationProvider
is more flexible than JaasAuthenticationProvider
, since it not dependent on the default Configuration
implementation.
下一个示例提供了一个 DefaultJaasAuthenticationProvider
的配置,它使用 InMemoryConfiguration
。请注意,Configuration
的自定义实现也可以轻松注入到 DefaultJaasAuthenticationProvider
中。
The next example provides a configuration of DefaultJaasAuthenticationProvider
that uses InMemoryConfiguration
.
Note that custom implementations of Configuration
can easily be injected into DefaultJaasAuthenticationProvider
as well.
<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
。
The JaasAuthenticationProvider
assumes that the default Configuration
is an instance of ConfigFile
.
This assumption is made in order to try to update the Configuration
.
The JaasAuthenticationProvider
then uses the default Configuration
to create the LoginContext
.
假设我们有一个 JAAS 登录配置文件,/WEB-INF/login.conf
,其内容如下:
Assume that we have a JAAS login configuration file, /WEB-INF/login.conf
, with the following contents:
JAASTest {
sample.SampleLoginModule required;
};
与所有 Spring Security Bean 一样,JaasAuthenticationProvider
是通过应用程序上下文配置的。以下定义对应于上述 JAAS 登录配置文件:
Like all Spring Security beans, the JaasAuthenticationProvider
is configured through the application context.
The following definitions would correspond to the above JAAS login configuration file:
<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>
Running as a Subject
如果已配置,JaasApiIntegrationFilter
尝试在 JaasAuthenticationToken
上以 Subject
身份运行。这意味着可以使用以下方法访问 Subject
:
If configured, the JaasApiIntegrationFilter
tries to run as the Subject
on the JaasAuthenticationToken
.
This means that the Subject
can be accessed using:
Subject subject = Subject.getSubject(AccessController.getContext());
你可以使用 jaas-api-provision 属性来配置此集成。当与依赖于填充 JAAS 主体的旧版或外部 API 集成时,此功能非常有用。
You can configure this integration by using the jaas-api-provision attribute. This feature is useful when integrating with legacy or external API’s that rely on the JAAS Subject being populated.