对于最新的稳定版本,请使用 Spring Security 6.5.3! |
预身份验证方案
示例包括 X.509、Siteminder 以及运行应用程序的 Java EE 容器的身份验证。 使用预身份验证时,Spring Security 必须:
-
识别发出请求的用户。
-
获取用户的权限。
详细信息取决于外部身份验证机制。
在 X.509 的情况下,用户可以通过其证书信息来识别,或者在 Siteminder 的情况下通过 HTTP 请求标头来识别用户。
如果依赖于容器身份验证,则通过调用getUserPrincipal()
方法。
在某些情况下,外部机制可能会为用户提供角色和权限信息。但是,在其他情况下,您必须从单独的来源获取授权,例如UserDetailsService
.
预身份验证框架类
由于大多数预身份验证机制都遵循相同的模式,因此 Spring Security 具有一组类,这些类提供了用于实现预身份验证身份验证提供程序的内部框架。
这消除了重复,并允许以结构化的方式添加新的实现,而无需从头开始编写所有内容。
如果您想使用 X.509 身份验证之类的东西,则无需了解这些类,因为它已经有一个命名空间配置选项,更易于使用和入门。
如果您需要使用显式 Bean 配置或计划编写自己的实现,则需要了解所提供的实现是如何工作的。
您可以在org.springframework.security.web.authentication.preauth
.
我们在这里只提供了一个大纲,因此您应该查阅 Javadoc 和适当的源代码。
抽象预身份验证处理过滤器
此类检查安全上下文的当前内容,如果它为空,则尝试从 HTTP 请求中提取用户信息并将其提交给AuthenticationManager
.
子类重写以下方法来获取此信息。
-
Java
-
Kotlin
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?
protected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?
调用这些后,过滤器会创建一个PreAuthenticatedAuthenticationToken
其中包含返回的数据并将其提交以供身份验证。
这里所说的“身份验证”实际上只是指进一步处理以加载用户的权限,但遵循标准的 Spring Security 身份验证架构。
与其他 Spring Security 身份验证过滤器一样,预身份验证过滤器具有authenticationDetailsSource
属性,默认情况下,它会创建一个WebAuthenticationDetails
对象来存储附加信息,例如会话标识符和原始 IP 地址details
属性的Authentication
对象。
如果可以从预身份验证机制中获取用户角色信息,则数据也存储在此属性中,详细信息实现了GrantedAuthoritiesContainer
接口。
这使身份验证提供程序能够读取外部分配给用户的权限。
接下来我们看一个具体的例子。
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
如果筛选器配置了authenticationDetailsSource
,这是此类的一个实例,则通过调用isUserInRole(String role)
方法。
该类从配置的MappableAttributesRetriever
.
可能的实现包括在应用程序上下文中对列表进行硬编码,并从<security-role>
信息web.xml
文件。
预身份验证示例应用程序使用后一种方法。
还有一个额外的阶段,其中角色(或属性)映射到 Spring SecurityGrantedAuthority
对象,使用已配置的Attributes2GrantedAuthoritiesMapper
.
默认值只是添加通常的ROLE_
前缀,但它使您可以完全控制行为。
预身份验证身份验证提供程序
预先经过身份验证的提供程序只需加载UserDetails
对象。
它通过委托给AuthenticationUserDetailsService
.
后者类似于标准UserDetailsService
但需要一个Authentication
对象而不仅仅是用户名:
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
此接口也可能有其他用途,但是,通过预身份验证,它允许访问打包在Authentication
对象,正如我们在上一节中看到的。
这PreAuthenticatedGrantedAuthoritiesUserDetailsService
class 会这样做。
或者,它可以委托给标准UserDetailsService
通过UserDetailsByNameServiceWrapper
实现。
http403禁止入口点
这AuthenticationEntryPoint
负责启动未经身份验证的用户的身份验证过程(当他们尝试访问受保护的资源时)。但是,在预先验证的情况下,这不适用。
您只需配置ExceptionTranslationFilter
如果不将预身份验证与其他身份验证机制结合使用,则使用此类的实例。
如果用户被AbstractPreAuthenticatedProcessingFilter
,导致 null 身份验证。
它总是返回一个403
-forbidden 响应代码(如果被调用)。
具体实施
X.509 身份验证在其自己的章节中进行了介绍。 在这里,我们介绍一些为其他预身份验证方案提供支持的类。
请求头身份验证 (Siteminder)
外部身份验证系统可以通过在 HTTP 请求上设置特定标头来向应用程序提供信息。一个著名的例子是 Siteminder,它在名为SM_USER
. 此机制由RequestHeaderAuthenticationFilter
类,它仅从标头中提取用户名。它默认使用SM_USER
作为标头名称。有关更多详细信息,请参阅 Javadoc。
使用这样的系统时,框架根本不执行身份验证检查,正确配置外部系统并保护对应用程序的所有访问非常重要。如果攻击者能够在未检测到的情况下伪造其原始请求中的标头,他们可能会选择他们想要的任何用户名。 |
Siteminder 示例配置
以下示例显示了使用此过滤器的典型配置:
<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>
<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="userDetailsService"/>
</bean>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>
我们在这里假设安全命名空间用于配置。
还假定您已添加UserDetailsService
(称为“userDetailsService”)添加到您的配置中以加载用户的角色。
Java EE 容器身份验证
这J2eePreAuthenticatedProcessingFilter
类从userPrincipal
属性的HttpServletRequest
.
此过滤器的使用通常与 Java EE 角色的使用相结合,如前面的 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 中所述。
代码库中有一个使用这种方法的示例应用程序,因此如果您有兴趣,请从 Github 获取代码并查看应用程序上下文文件。