对于最新的稳定版本,请使用 Spring Security 6.4.1spring-doc.cadn.net.cn

预身份验证方案

示例包括 X.509、Siteminder 和运行应用程序的 Java EE 容器的身份验证。 使用预身份验证时,Spring Security 必须:spring-doc.cadn.net.cn

详细信息取决于外部身份验证机制。 在 X.509 的情况下,用户可能通过其证书信息来识别,在 Siteminder 的情况下,可以通过 HTTP 请求标头来识别。 如果依赖容器身份验证,则通过调用getUserPrincipal()方法。 在某些情况下,外部机制可能会为用户提供角色和权限信息。但是,在其他情况下,您必须从单独的来源(如UserDetailsService.spring-doc.cadn.net.cn

预身份验证框架类

因为大多数预身份验证机制都遵循相同的模式,所以 Spring Security 有一组类,这些类为实现预身份验证的身份验证提供程序提供了一个内部框架。 这消除了重复,并允许以结构化的方式添加新的实现,而无需从头开始编写所有内容。 如果您想使用类似 X.509 身份验证的东西,则无需了解这些类,因为它已经有一个命名空间配置选项,更易于使用和开始使用。 如果您需要使用显式 bean 配置或计划编写自己的实现,则需要了解所提供的实现是如何工作的。 您可以在org.springframework.security.web.authentication.preauth. 我们在此处仅提供大纲,因此您应该在适当的情况下查阅 Javadoc 和源代码。spring-doc.cadn.net.cn

AbstractPreAuthenticatedProcessingFilter

此类检查安全上下文的当前内容,如果为空,则尝试从 HTTP 请求中提取用户信息并将其提交到AuthenticationManager. 子类会覆盖以下方法来获取此信息。spring-doc.cadn.net.cn

覆盖 AbstractPreAuthenticatedProcessingFilter
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-doc.cadn.net.cn

与其他 Spring Security 身份验证过滤器一样,预身份验证过滤器具有authenticationDetailsSource属性,默认情况下,它会创建一个WebAuthenticationDetails对象来存储其他信息,例如会话标识符和原始 IP 地址details属性的Authentication对象。 如果可以从预身份验证机制获取用户角色信息,则数据也存储在此属性中,详细信息实现GrantedAuthoritiesContainer接口。 这使身份验证提供程序能够读取从外部分配给用户的权限。 接下来,我们来看一个具体的例子。spring-doc.cadn.net.cn

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

如果过滤器配置了authenticationDetailsSource,它是该类的一个实例,则权限信息是通过调用isUserInRole(String role)方法。 该类从配置的MappableAttributesRetriever. 可能的实现包括在应用程序上下文中对列表进行硬编码,并从<security-role>信息以web.xml文件。 预身份验证示例应用程序使用后一种方法。spring-doc.cadn.net.cn

还有一个额外的阶段,其中角色(或属性)被映射到 Spring SecurityGrantedAuthority对象Attributes2GrantedAuthoritiesMapper. 默认值只是添加了通常的ROLE_前缀添加到名称中,但它使您可以完全控制行为。spring-doc.cadn.net.cn

PreAuthenticatedAuthenticationProvider

预先验证的提供程序除了加载UserDetails对象的 URL。 它通过委托给AuthenticationUserDetailsService. 后者类似于标准UserDetailsService但是需要一个Authenticationobject 而不仅仅是 user name 的 URL 中:spring-doc.cadn.net.cn

public interface AuthenticationUserDetailsService {
	UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

此接口可能还有其他用途,但是,通过预身份验证,它允许访问打包在Authenticationobject,正如我们在上一节中看到的那样。 这PreAuthenticatedGrantedAuthoritiesUserDetailsServiceclass 执行此作。 或者,它可以委托给标准UserDetailsService通过UserDetailsByNameServiceWrapper实现。spring-doc.cadn.net.cn

Http403ForbiddenEntryPoint

AuthenticationEntryPoint负责启动未经身份验证的用户的身份验证过程(当他们尝试访问受保护的资源时)。但是,在预身份验证的情况下,这不适用。 您只需配置ExceptionTranslationFilter如果不将预身份验证与其他身份验证机制结合使用,则使用此类的实例。 如果用户被AbstractPreAuthenticatedProcessingFilter,导致 null 身份验证。 它总是返回一个403-forbidden 响应代码。spring-doc.cadn.net.cn

具体实现

X.509 身份验证在其单独的章节中介绍。 在这里,我们看一些为其他预身份验证场景提供支持的类。spring-doc.cadn.net.cn

请求标头身份验证 (Siteminder)

外部身份验证系统可以通过在 HTTP 请求上设置特定标头来向应用程序提供信息。 一个著名的示例是 Siteminder,它将用户名传入名为SM_USER. 此机制由RequestHeaderAuthenticationFilter类,它只从 header 中提取用户名。 它默认使用 nameSM_USER作为标头名称。 有关更多详细信息,请参阅 Javadoc。spring-doc.cadn.net.cn

当使用这样的系统时,框架根本不执行身份验证检查,正确配置外部系统并保护对应用程序的所有访问非常重要。 如果攻击者能够在其原始请求中伪造标头而不被检测到,则他们可能会选择他们想要的任何用户名。spring-doc.cadn.net.cn

Siteminder 示例配置

以下示例显示了使用此筛选条件的典型配置:spring-doc.cadn.net.cn

<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>

我们在这里假设 security 命名空间用于配置。 还假定您已添加了UserDetailsService(称为“userDetailsService”)添加到您的配置中,以加载用户的角色。spring-doc.cadn.net.cn

Java EE 容器身份验证

J2eePreAuthenticatedProcessingFilter类从userPrincipal属性的HttpServletRequest. 此过滤器的使用通常与使用 Java EE 角色结合使用,如前面的 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 中所述。spring-doc.cadn.net.cn

代码库中有一个使用此方法的示例应用程序,因此如果您有兴趣,请从 Github 获取代码并查看应用程序上下文文件。spring-doc.cadn.net.cn